-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrss.xml
More file actions
2 lines (2 loc) · 152 KB
/
Copy pathrss.xml
File metadata and controls
2 lines (2 loc) · 152 KB
1
2
<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:a="http://www.w3.org/2005/Atom" xmlns:c="http://purl.org/rss/1.0/modules/content/"><channel><title>CC的部落格</title><link>https://blog.ccknbc.cc/</link><description>CC康纳百川</description><language>zh-CN</language><copyright>All rights reserved 2026, CC康纳百川</copyright><lastBuildDate>Sat, 22 Aug 2026 16:42:51 GMT</lastBuildDate><generator>Hexo</generator><image><url>https://cdn.jsdmirror.com/gh/ccknbc-backup/cdn/logo/CC.png</url><title>CC的部落格</title><link>https://blog.ccknbc.cc/</link></image><a:link href="https://blog.ccknbc.cc/rss.xml" rel="self" type="application/rss+xml"/><item><title><![CDATA[<font style=color:rgb(38, 38, 38);>2023《好好》线上演唱会</font>]]></title><link>https://blog.ccknbc.cc/posts/%3Cfont%20style=%22color:rgb(38,%2038,%2038);%22%3Esong-about-you-live-in-the-sky-2023%3C/font%3E/</link><description><![CDATA[<font style="color:rgb(38, 38, 38);">刘若英X苏慧伦X丁当X白安 2023《好好》线上演唱会 Song About You live in the sky 2023</font>]]></description><author>CC康纳百川</author><category domain="https://blog.ccknbc.cc/categories/%E9%9F%B3%E4%B9%90/">音乐</category><category domain="https://blog.ccknbc.cc/tags/%E5%8F%B0%E6%B9%BE/">台湾</category><category domain="https://blog.ccknbc.cc/tags/%E9%9F%B3%E4%B9%90/">音乐</category><pubDate>Sat, 22 Aug 2026 16:42:51 GMT</pubDate><c:encoded><![CDATA[<blockquote><p>版权归属 台湾 相信音乐</p></blockquote><p>刘若英X苏慧伦X丁当X白安</p><p>2023《好好》线上演唱会</p><p>Song About You live in the sky 2023</p><h2 id="歌单一览">歌单一览<a class="fa-solid fa-hashtag" href="#歌单一览"></a></h2><blockquote><p><strong>已在视频中标出</strong></p></blockquote><hr><p>苏慧伦part</p><p>0:30 鸭子</p><p>4:27 被动</p><p>8:18说话</p><p>9:09 严重</p><p>13:12说话</p><p>13:24 恋恋真言</p><p>17:17 在我生命中的每一天 feat.丁当</p><hr><p>丁当part</p><p>21:58 开头</p><p>22:39 夜猫</p><p>26:13 花火</p><p>30:18说话</p><p>31:07 猜不透</p><p>35:12说话</p><p>37:25 女字旁</p><p>41:56 我爱他</p><hr><p>白安 part</p><p>46:54 不够特别的我不要</p><p>51:41 刚好</p><p>56:01说话</p><p>56:39 是什么让我遇见这样的你</p><p>1:00:39 没有人写歌给你过吧</p><p>1:05:39 让我逃离平庸的生活</p><hr><p>刘若英 part</p><p>1:10:25 所有相爱的人啊</p><p>1:14:28 成全</p><p>1:18:57说话</p><p>1:20:55 固执</p><p>1:25:47 缩影</p><p>1:29:30 talking feat.白安</p><p>1:31:20 妈妈 feat.白安</p><p>1:35:51 后来</p><p>1:40:52 快乐天堂 feat.苏慧伦、丁当、白安</p><hr><p>女加上子 每个女子生而为好</p><p>该对自己好 该好好疼爱自己</p><p>女子女子 就是好好</p><p>好歌相伴 好上加好</p><p>《好好》线上演唱会</p><p>一场女子们的闺密音乐聚会</p><p>宜尽兴 宜微醺 宜舒心 宜走心</p><p>妳有多久没有好好跟自己说说话了?</p><p>妳有多久没有好好聆听心底声音了?</p><p>妳有多久没有好好跟好友聊聊天了?</p><p>妳有多久没有好好欣赏美好事物了?</p><p>女子,要好好去爱,更要好好爱自己。</p><p>「3月8日」是一年一度的「国际妇女节」 (International Women’s Day),提醒每个女子要爱自己,更能去爱别人、去爱这个世界。 在这个这个专属于女子的节日,刘若英X苏慧伦X丁当X白安,四个女子的美好相遇,要在38妇女节的周三夜,以音乐用心地打造出一场属于每个你的 “Lady’s Night”,你可以与你自己,也可以与好闺密们,一起好好享受、好好尽欢、好好聆听一首首动人的女子心声。</p><p>如水 如石 如光 如树</p><p>一场音乐与自然的飨宴</p><p>将美好谱写 如歌而行</p><p>当音乐遇见自然 当内心遇见自己</p><p>美的时节 好的相遇</p><p>女子女子 好好与你以歌相聚</p><p>「女」加上「子」等于「好」,「女子」加上「女子」就是「好好」,好上加好! 「好好女声」刘若英、苏慧伦、丁当、白安,春暖花开时节献唱,,以歌相聚在《好好》线上演唱会,不仅渲染多首个人经典好歌,彼此间更有精彩的合唱新火花! 《好好》演唱会以「女野」概念,结合「水、石、光、树」为主题,女子在自然旷野里吟唱,呈现出如水之柔美、如石之坚强、如光之魔幻、如树之实在的演唱氛围。</p><p>新的一年一切都在慢慢变好,刘若英、苏慧伦、丁当、白安,四美女子以美好歌声陪伴每个认真生活、认真爱的女子,一起告别因疫情闷久的坏坏情绪,迎接温暖美丽的好好心情</p><h2 id="流媒体平台">流媒体平台<a class="fa-solid fa-hashtag" href="#流媒体平台"></a></h2><p><a href="https://t.cn/A6CNy1Rx">QQ音乐</a> | <a href="https://t.cn/A6CodoGG">网易云音乐</a> | <a href="https://t.cn/A6CNylOl">酷狗音乐</a> | <a href="https://t.cn/A6CNylOW">酷我音乐</a> | <a href="https://t.cn/A6CKz5LV">咪咕音乐</a> | <a href="https://t.cn/A6CKz5Lq">汽水音乐</a></p>]]></c:encoded></item><item><title>很棒的状态页面</title><link>https://blog.ccknbc.cc/posts/undefined/</link><description><![CDATA[<p>本文首发在<a href="https://www.yuque.com/ccknbc/blog/23/"><strong>语雀</strong></a></p>
<p>自动同步更新至<a]]></description><author>CC康纳百川</author><pubDate>Sat, 22 Aug 2026 16:42:51 GMT</pubDate><c:encoded><![CDATA[<p>本文首发在<a href="https://www.yuque.com/ccknbc/blog/23/"><strong>语雀</strong></a></p><p>自动同步更新至<a href="https://blog.ccknbc.cc/posts/awesome-status-pages/"><strong>CC的部落格</strong></a></p><h2 id="Awesome-status-pages">Awesome status pages<a class="fa-solid fa-hashtag" href="#Awesome-status-pages"></a></h2><p>Awesome list of status pages open source software, online services and public status pages of major internet companies</p><h2 id="Opensource">Opensource<a class="fa-solid fa-hashtag" href="#Opensource"></a></h2><ul><li><a href="https://cachethq.io/">Cachet</a> - Laravel based status page system for everyone.</li><li><a href="https://github.com/weeblrpress/clearstatus/">ClearStatus</a> - Hugo-based status page, supports Netlify. Supports events from Github, Gitlab or any git repo with markdown.</li><li><a href="https://github.com/jayfk/statuspage">Corestats</a> - turn GitHub issues into a status page</li><li><a href="https://github.com/cstate/cstate">cState</a> - Simple, dev friendly, and free to host (Netlify & GitHub Pages)</li><li><a href="https://github.com/TwinProduction/gatus">Gatus</a> - Automated service health dashboard</li><li><a href="https://github.com/tadhglewis/issue-status">Issue Status</a> - Simple, modern and flexible status page</li><li><a href="https://github.com/tmobile/kardio">Kardio</a> - Simple Health Status Tool with Rich UI for Services deployed on Kubernetes and other platforms.</li><li><a href="https://lambstatus.github.io">LambStatus</a> (<em>Deprecated</em>)</li><li><a href="https://monitoror.com/">Monitoror</a> - monitoring wallboard</li><li><a href="https://github.com/Pryx/server-status">Server-Status</a></li><li><a href="http://www.stashboard.org/">StashBoard</a> - Python, for Google App Engine (<em>Deprecated</em>)</li><li><a href="https://github.com/Cyclenerd/static_status">Static status</a> - Bash script to generate a static status page</li><li><a href="https://github.com/hunterlong/statping">Statping</a></li><li><a href="https://marquez.co/statusfy">Statusfy</a></li><li><a href="https://github.com/sanathp/statusok">StatusOK</a></li><li><a href="https://github.com/darkpixel/statuspage">statuspage</a> - Simple self-hosted open source status page site written in Django (inspired by <a href="https://cachethq.io/">Cachet</a>)</li><li><a href="https://staytus.co/">Staytus</a> (<em>Deprecated</em>)</li><li><a href="https://github.com/ianheggie/health_check">health_check</a> - Simple health check of Rails app for use with uptime checking sites like newrelic and pingdom</li><li><a href="https://github.com/rails-engine/status-page">status-page</a> - Mountable status page for your Rails application, to check Cache, Redis, Sidekiq</li><li><a href="https://github.com/lbeder/health-monitor-rails">health-monitor-rails</a> - A Rails plugin which provides a health checking and monitoring API of various services and application aspects</li><li><a href="https://github.com/valeriansaliou/vigil">Vigil</a> - Microservices Status Page. Monitors a distributed infrastructure and sends alerts (Slack, SMS, etc.).</li><li><a href="https://github.com/EvotecIT/Statusimo">Statusimo</a> - A PowerShell module that is able to generate a status page entirely from PowerShell.</li><li><a href="https://github.com/eidam/cf-workers-status-page">Workers Status Page</a> - Cloudflare Workers (completely on the edge) powered monitoring & status page.</li><li><a href="https://github.com/upptime/upptime">Upptime</a> - monitor and status page powered by GitHub</li><li><a href="https://github.com/RatherLogical/Uptimon">Uptimon</a> - A PHP powered status page/monitoring solution.</li><li><a href="https://github.com/bderenzo/tinystatus">Tinystatus</a> - A tiny static status page generator (written in pure shell)</li></ul><h2 id="Services">Services<a class="fa-solid fa-hashtag" href="#Services"></a></h2><ul><li><a href="https://www.adminlabs.com/status-page/">AdminLabs Statuspage</a></li><li><a href="https://www.appbeat.io/">AppBeat Monitoring</a> - uptime monitoring with integrated status page</li><li><a href="https://asserted.io"><s>Asserted.io</s></a>~~ - uptime tests written in Mocha ~~<s><em>(Discontinued)</em></s></li><li><a href="https://www.freshworks.com/statuspage/">FreshStatus</a></li><li><a href="https://hetrixtools.com">HetrixTools</a> - uptime monitoring for ips and websites with an integrated status page</li><li><a href="https://tryhexadecimal.com">Hexadecimal</a> - uptime & certificate monitoring and hosted status pages</li><li><a href="https://hund.io/">Hund</a></li><li><a href="https://instatus.com">Instatus</a> - Free online service with a static & customizable page.</li><li><a href="https://lambstatus.github.io/">LambStatus</a></li><li><a href="https://nixstats.com/">NixStats</a> - service for servers, web, log and blacklists monitoring</li><li><a href="https://pagefate.com">PageFate.com</a> - free online service with customisable design</li><li><a href="https://www.ping2me.io/">ping2me</a> - monitor endpoints to make sure that they are online.</li><li><a href="https://pingpong.one">PingPong</a> - incident management, uptime & certificate monitoring and hosted status pages</li><li><a href="https://www.sorryapp.com">Sorry™</a></li><li><a href="https://www.squadcast.com">Squadcast</a> - On-Call & SRE platform with StatusPages built-in</li><li><a href="https://status.io">Status.io</a></li><li><a href="https://statuskeeper.com/">StatusKeeper</a></li><li><a href="https://statuskit.com/">StatusKit</a></li><li><a href="https://www.statuspage.io">Statuspage.io</a> - online service from Atlassian</li><li><a href="https://statuspal.io">Statuspal</a> - Hosted status pages & monitoring.</li><li><a href="https://statusy.co"><s>Statusy</s></a>~~ ~~<s><em>(Discontinued)</em></s></li><li><a href="https://updown.io/">UpDown.io</a> - uptime monitoring with flexible status with rest api</li><li><a href="https://uptimerobot.com/">Uptime Robot</a></li><li><a href="https://www.uptimetoolbox.com/">UptimeToolbox</a> - Website/Server monitors with status pages.</li></ul><h2 id="Public-status-pages">Public status pages<a class="fa-solid fa-hashtag" href="#Public-status-pages"></a></h2><ul><li><a href="https://status.adobe.com/">Adobe System Status</a> - Adobe services status</li><li><a href="https://cloudharmony.com/status-for-akamai">Akamai Status</a> - Akamai Service Status</li><li><a href="https://status.aws.amazon.com/">Amazon AWS Service health dashboard</a></li><li><a href="https://www.apple.com/support/systemstatus/">Apple Support System Status</a> - Apple support status</li><li><a href="https://status.box.com/">Box Status</a> - <a href="http://Box.net">Box.net</a> status</li><li><a href="https://www.cloudflarestatus.com/">Cloudflare Status</a> - Cloudflare System Status</li><li><a href="https://cloudharmony.com/status-of-cdn-for-aws">CloudFront Status</a> - Amazon CloudFront Service Status</li><li><a href="https://status.datadoghq.com/">Datadog Status</a> - the status of Datadog.</li><li><a href="https://status.digitalocean.com/">DigitalOcean Status</a> - DigitalOcean Status page</li><li><a href="https://status.discordapp.com/">Discord App Status</a> - Discord App (videoconferencing, audioconferencing) status page</li><li><a href="https://developers.facebook.com/status/dashboard/">Facebook Platform Status</a> - Facebook platform status page</li><li><a href="https://status.fastly.com/">Fastly Status Page</a> - Fastly Status</li><li><a href="https://status.github.com/api">GitHub Status API</a> - GitHub status using REST API</li><li><a href="https://status.github.com/">GitHub Status</a> - GitHub status page</li><li><a href="https://status.gitlab.com">GitLab System Status</a> - GitLab status page</li><li><a href="https://status.cloud.google.com/">Google Cloud Status</a> - Status of Google Cloud</li><li><a href="https://www.google.com/appsstatus">Google GSuite Appstatus</a> - Google Applications (G Suite) online status page</li><li><a href="https://status.heroku.com/">Heroku Status</a> - Heroku status page</li><li><a href="https://status.ads.microsoft.com/">Microsoft Advertizement Status</a> - Microsoft Advertizement status page</li><li><a href="https://status.azure.com/ru-ru/status">Microsoft Azure Status</a> - Microsoft Azure status page</li><li><a href="https://status.office365.com/">Microsoft Office365 Status</a> - Microsoft Office365 status page</li><li><a href="https://www.paypal-status.com/product/production">Paypal Status Page</a></li><li><a href="https://www.pintereststatus.com/">Pinterest Status Page</a></li><li><a href="https://status.rackspace.com/">Rackspace System Status</a> - Rackspace hosting and services status page</li><li><a href="https://www.redditstatus.com/">reddit Status</a> - reddit Social Media status page</li><li><a href="https://support.skype.com/en/status/">Skype Status</a> - Microsoft Skype Status page</li><li><a href="https://status.slack.com/">Slack Status</a> - Slack, chat platform, status page</li><li><a href="https://api.twitterstat.us/">Twitter API Status</a> - Twitter API status page</li><li><a href="https://grafana.wikimedia.org/d/000000479/frontend-traffic?orgId=1">Wikipedia Frontend Monitoring</a> - Graphana based status page replacement for Wikipedia</li><li><a href="https://status.zoom.us/">Zoom Cloud Status</a> - Zoom (videoconferencing) status page</li></ul><h2 id="目前使用">目前使用<a class="fa-solid fa-hashtag" href="#目前使用"></a></h2><p><a href="https://cc.instatus.com/"><strong>Instatus</strong></a>(中文)| <a href="https://ccknbc.statuspage.io/"><strong>Statuspage</strong></a>(English)</p><p>因为 Instatus 我贡献了翻译,而且相较于其他免费产品,可自定义的地方实在太多了(好评,白嫖党的胜利)</p><p>而 Statuspage 主要是他可链接的第三方实在太多了,免费帐户的话能添加 25 个组件,反正也没有外国人看我,就当自用吧</p><p>配合 Freshping, Uptimerobot 等监控联动,这两个均可自动化向推特发送通知,当然 Uptimerobot 自身推送的方式也很多,RSS, Telegram, Webhook 等满足日常需要了。此外良心的他们对于订阅更新支持也很完善,虽然根本没人会去订阅,但还是要有这些功能对吧,高大上点(不是)</p><p>不过对于使用中文为主的我们来说,Instatus 是您的不二选择,时区,时间格式,语言什么的自定义太友好了,免费账号是完全够个人站长使用的,但是他的 embed 目前来说我希望能自适应大小,深色模式等,反正还很期待啦。而说到 embed, Statuspage 的 embed 个人觉得好看点吧,可以选择弹窗模式,悬浮模式,基础模式,徽标模式,自适应也不错,不过因为不支持中文(就是懒得自己在再整,官方那个代码都两年没动了)。此外 <a href="https://instatus.com/out"><strong>Instatus OUT</strong></a> 提供了网页端或者客户端(状态栏)快捷监控第三方的服务,而未来 Instatus 还会带来哪些服务呢,让我们共同期待吧!</p><hr><p>但自从 <a href="https://www.vercel-status.com/incidents/r758bhbklgfd"><strong>Vercel 事件</strong></a> 后,我们自己的状态页不受影响,IP换到了中国专用IP,但是 Instatus 官方还是原来的 A记录 IP,导致中国大陆用户无法访问其状态页和官网,这对用户体验来说是没什么,但对于站长就麻烦点了,得使用代理才能更新事件。不过 API, 邮件, WebHook 等方式应该可以解决,但官网控制面板更加方便,然后和开发者沟通更换了 IP, 目前一切正常,并且提前拥有了多语言和深色模式的支持,未来也会有其他功能,静态网页访问就是快!!!</p>]]></c:encoded></item><item><title>一款简洁却不简单的 m3u8 下载工具</title><link>https://blog.ccknbc.cc/posts/a-simple-but-not-simple-m3u8-download-tool/</link><description>一款简洁却不简单的 m3u8 下载工具</description><author>CC康纳百川</author><category domain="https://blog.ccknbc.cc/categories/%E5%B7%A5%E5%85%B7/">工具</category><category domain="https://blog.ccknbc.cc/tags/%E5%B7%A5%E5%85%B7/">工具</category><pubDate>Sat, 22 Aug 2026 16:42:51 GMT</pubDate><c:encoded><![CDATA[<p>本文首发在<a href="https://www.yuque.com/ccknbc/blog/19/"><strong>语雀</strong></a></p><p>自动同步更新至<a href="https://blog.ccknbc.cc/posts/a-simple-but-not-simple-m3u8-download-tool/"><strong>CC的部落格</strong></a></p><p><a href="https://github.com/nilaoda/N_m3u8DL-CLI">官方仓库</a></p><p><img src="https://cdn.nlark.com/yuque/0/2021/gif/8391407/1610273643341-942cd95d-6f1e-4356-afc9-d5961c7d078a.gif" alt="" loading="lazy"></p><p>批量下载优酷m3u8</p><p><img src="https://cdn.nlark.com/yuque/0/2021/gif/8391407/1610273775655-7e8c3956-6d5a-4760-a59b-d02e6c21126e.gif" alt="" loading="lazy"></p><p>LINETV(台湾站解析)<br><img src="https://cdn.nlark.com/yuque/0/2021/gif/8391407/1610273823214-764f768e-4b64-4073-8793-498c61a30285.gif" alt="" loading="lazy"></p><p>其实 SimpleG 提供了 CLI 更直观简单的调用方式,因此更加方便快捷,解密,录直播必备。</p>]]></c:encoded></item><item><title>Waline 评论系统部署日志</title><link>https://blog.ccknbc.cc/posts/waline-comments-system-deployment-logs/</link><description>Waline 评论系统部署日志,希望你也能用上这款评论系统</description><author>CC康纳百川</author><category domain="https://blog.ccknbc.cc/categories/%E5%B7%A5%E5%85%B7/">工具</category><category domain="https://blog.ccknbc.cc/tags/%E5%B7%A5%E5%85%B7/">工具</category><pubDate>Sat, 22 Aug 2026 16:42:51 GMT</pubDate><c:encoded><![CDATA[<div class="note danger simple"><p>本文大部分内容已作废,请直接查看<a href="https://waline.js.org/"><strong>官方文档</strong></a></p></div><p>本文首发在<a href="https://www.yuque.com/ccknbc/blog/20/"><strong>语雀</strong></a></p><p>自动同步更新至<a href="https://blog.ccknbc.cc/posts/waline-commens-system-deployment-logs/"><strong>CC的部落格</strong></a></p><p><strong>本文仅作为官方文档的补充,若有错误,还望指正</strong></p><p><a href="https://ccknbc.now.sh/posts/waline-commens-system-deployment-logs/#Todo">Waline 评论系统部署日志</a></p><hr><p>Waline - 一款从 <a href="https://valine.js.org">Valine</a> 衍生的带后端评论系统。可以将 Waline 等价成 With backend Valine.</p><h2 id="特性">特性<a class="fa-solid fa-hashtag" href="#特性"></a></h2><ul><li>快速</li><li>真·安全</li><li>Markdown 语法支持</li><li>轻量易用</li><li>免费部署</li><li>多种部署部署方式和存储服务支持,每列选择一项多达 84 种(可以更多)部署方式任君选择</li></ul><table><thead><tr><th></th><th>Waline</th><th></th></tr></thead><tbody><tr><td><strong>客户端脚本</strong></td><td><strong>服务端部署</strong></td><td><strong>数据存储</strong></td></tr><tr><td><a href="https://waline.js.org/"><strong>@waline/client</strong></a></td><td>Vercel</td><td>LeanCloud</td></tr><tr><td><a href="https://minivaline.js.org/"><strong>MiniValine</strong></a></td><td>CloudBase</td><td>CloudBase</td></tr><tr><td><a href="https://github.com/innc11/AprilComment"><strong>AprilComment</strong></a></td><td>Docker</td><td>MongoDB</td></tr><tr><td></td><td>独立部署</td><td>MySQL</td></tr><tr><td></td><td></td><td>SQLite</td></tr><tr><td></td><td></td><td>PostgreSQL</td></tr><tr><td></td><td></td><td>GitHub</td></tr></tbody></table><p>对于想免费使用的用户, <code>Vercel</code> + <code>LeanCloud(国际版)</code> 是不错的选择,不过<code>Deta</code>一个服务就能解决所有问题而且还快点,如果你主要面向对象为大陆用户,使用 <code>CloudBase</code> 部署也是个不错的选择,它在海外表现也没那么差,或者您仅使用 <code>CloudBase</code> 来做数据存储</p><p><font style="color:#333333;"><div class="note warning simple"><p>如果您使用 </font> <code>Vercel</code> + <code>LeanCloud</code> ,并且使用 <code>Vercel</code> 发送评论通知,您不必担心 LeanCloud 流控问题,并且之前使用过 Valine 或者部署过 <code>Valine-Admin</code> 项目的可以直接拿来用;对于评论转移,官方提供了<a href="https://waline.js.org/migration/tool.html">迁移助手</a>供您使用,不用担心之前评论丢失的问题<font style="color:#333333;"></p></div></font></p><h2 id="Todo">Todo<a class="fa-solid fa-hashtag" href="#Todo"></a></h2><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;> 微信通知</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>QQ 通知</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>Telegram 通知</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>Akismet</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>文章统计</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>多语言同步</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>自定义语言支持</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;> 登录支持</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>评论管理</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>评论删除</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p>其它数据库支持 </font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>基于 IP 的发布评论频率限制</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>基于关键词的评论过滤限制</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>IP 黑名单</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>重复内容检测</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>CloudBase 腾讯云开发部署支持</font><font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox green checked'><input type="checkbox" checked="checked"/> <p></font><font style=color:#333333;>社交登录</p> </div></font></p><p><font style="color:#333333;"><div class='checkbox red'><input type="checkbox" /> <p></font>AWS</p> </div></font></p><p><font style="color:#333333;"><div class='checkbox red'><input type="checkbox" /> <p></font>置顶评论<font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox red'><input type="checkbox" /> <p></font>评论赞踩<font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class='checkbox blue'><input type="checkbox" /> <p></font>其它…<font style=color:#333333;></p> </div></font></p><p><font style="color:#333333;"><div class="note warning simple"><p>目前社交登录仅支持 </font><code><font style="color:#333333;">GitHub</font></code> <font style="color:#333333;">, 未来会支持更多平台</p></div></font></p><hr><h2 id="Vercel-LeanCloud-部署">Vercel + LeanCloud 部署<a class="fa-solid fa-hashtag" href="#Vercel-LeanCloud-部署"></a></h2><p>这部分请前往<a href="https://waline.js.org/quick-start.html">官方文档</a>查看,不过需要注意的是如果你的 <code>GitHub</code> 账号主邮箱是 <code>QQ</code> 邮箱的话建议更改为其他邮箱(毕竟他们认为QQ邮箱是垃圾邮箱)再去注册 Vercel(或者你可以选择给客服发一封邮件让他们帮忙解锁你的账号),环境变量配置部分官方文档也写了,这里不再赘述</p><p>如果您之前用过 Valine,那么关于 LeanCloud 部分你就不用做什么了,数据兼容,拿到那几个 <code>key</code> 即可</p><h3 id="配置项">配置项<a class="fa-solid fa-hashtag" href="#配置项"></a></h3><p>这个可直接参考官方文档按需进行配置即可,因为目前云开发因众所周知的原因不支持连接 <code>Telegram</code> 服务器,所以如果您要配置电报新评论通知,请使用 Vercel 进行配置,不过因为目前没有异步通知,加上反垃圾检测等功能,发布评论可能需要很长时间,这个我使用了 LeanCloud 来继续帮我发送通知(反正我也没什么评论,流控问题第二天补发评论也不是不可)</p><p><font style="color:#333333;"><div class="note warning simple"><p>对于邮件通知部分,目前的设定是,对于新评论,如果博主配置了 QQ/微信/Telegram 通知中任意一种或多种,则邮件通知将会取消,而对于回复(子评论),博主和被回复者(如果填了邮箱的话)均可收到邮件通知</p></div></font></p><p><font style="color:#333333;">我目前使用的 Hexo Butterfly 主题已经从 3.5.0 beta3 版本起内置了 Waline 评论系统,如果您使用老版本主题请升级,或者根据您所用版本的 Valine 模板 pug 来照葫芦画瓢,根据官方配置进行对应修改,主题中 option 为可选配置,万一将来增加了某些配置,主题不必为此升级, bg 为主题配置项</font></p><p>这里注意一下 serverURL 以及环境变量里的 SITE_URL 网址最后的斜杠因为作者没做兼容,所以不要带上 / ,导致跳转不到对应评论界面</p><p>客户端脚本里可以通过 <code>langMode.admin</code> 这个配置自定义角标的文案,例如:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">waline</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> <span class="title class_">Waline</span> = <span class="built_in">require</span>(<span class="string">'@waline/client'</span>);</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">Waline</span>({</span><br><span class="line"> <span class="attr">el</span>: <span class="string">'#waline-comment'</span>,</span><br><span class="line"> <span class="attr">serverURL</span>: <span class="string">'https://waline.vercel.app'</span>,</span><br><span class="line"> <span class="attr">path</span>: <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">pathname</span>,</span><br><span class="line"> <span class="attr">visitor</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">lang</span>: location.<span class="property">pathname</span>.<span class="title function_">startsWith</span>(<span class="string">'/en/'</span>) ? <span class="string">'en'</span> : <span class="string">'zh-CN'</span>,</span><br><span class="line"> <span class="attr">langMode</span>: {</span><br><span class="line"> <span class="attr">admin</span>: location.<span class="property">pathname</span>.<span class="title function_">startsWith</span>(<span class="string">'/en/'</span>) ? <span class="string">'Administrator'</span> : <span class="string">'可爱的管理员'</span></span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>对于同主题在主题配置里找到 <code>waline</code> 配置项相关内容</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># waline - A simple comment system with backend support fork from Valine</span></span><br><span class="line"><span class="comment"># https://waline.js.org/</span></span><br><span class="line"><span class="attr">waline:</span></span><br><span class="line"> <span class="attr">serverURL:</span> <span class="string">https://waline.ccknbc.ml</span> <span class="comment"># Waline server address url</span></span><br><span class="line"> <span class="attr">avatar:</span> <span class="string">monsterid</span> <span class="comment"># gravatar style https://zh-tw.gravatar.com/site/implement/images/#default-image</span></span><br><span class="line"> <span class="attr">bg:</span> <span class="comment"># waline background</span></span><br><span class="line"> <span class="attr">emojiCDN:</span> <span class="string">https://cdn.jsdelivr.net/gh/GamerNoTitle/ValineCDN@master/</span></span><br><span class="line"> <span class="attr">visitor:</span> <span class="literal">false</span></span><br><span class="line"> <span class="attr">option:</span> </span><br><span class="line"> <span class="attr">pageSize:</span> <span class="number">10</span></span><br><span class="line"> <span class="attr">requiredFields:</span> <span class="string">mail</span></span><br><span class="line"> <span class="comment"># anonymous: false </span></span><br><span class="line"> <span class="attr">placeholder:</span> </span><br><span class="line"> <span class="attr">avatarCDN:</span> <span class="string">https://sdn.geekzu.org/avatar/</span></span><br><span class="line"> <span class="comment">#https://valinecdn.bili33.top/</span></span><br><span class="line"> <span class="attr">langMode:</span></span><br><span class="line"> <span class="attr">admin:</span> <span class="string">博主兼管理员</span></span><br><span class="line"> <span class="attr">nick:</span> <span class="string">昵称(选填)</span></span><br><span class="line"> <span class="attr">mail:</span> <span class="string">邮箱(必填)</span></span><br><span class="line"> <span class="attr">link:</span> <span class="string">网址(选填)</span></span><br><span class="line"> <span class="attr">sofa:</span> <span class="string">这里冷冷清清的,快来留下脚印吧!</span></span><br><span class="line"> <span class="comment"># 如果你查看了源码,会发现还有这个可以配置 copyRight: false,但不建议大家设为 false 啦,保留也没什么的(没错,我不要脸)</span></span><br></pre></td></tr></table></figure><p><s>还有就是可能有人会觉得默认邮件通知模板太单调,想和 Valine-Admin 一样切换模板,其实有这个配置的,只是目前的方法是写在环境变量中,而环境变量限制长度(大小),或者说是不适合这种方式配置,如果要改的话可以先查看</s><a href="https://github.com/lizheming/waline/issues/106"><s>issues/106</s></a><s>相关内容,或者等以后优化再说;当然如果你的评论不是很多,并且之前配置过 Valine-Admin,那么你仍然可以使用 LeanCloud 来做异步发送通知,关闭默认的通知配置,或者使用 js 推送</s></p><p>关于邮件模板大家可查看<a href="https://waline.js.org/server/notification.html#%E9%80%9A%E7%9F%A5%E6%A8%A1%E6%9D%BF">官方文档</a>相关章节,或者使用<a href="#%E9%82%AE%E4%BB%B6%E9%80%9A%E7%9F%A5%E6%A8%A1%E6%9D%BF">附录提供的邮件通知模板</a>,也提交了 PR</p><p><a href="https://waline.js.org/server/basic.html#%E8%AF%84%E8%AE%BA-hooks">评论 Hooks</a>,可以根据官方的例子自己做一些配置,相比于其他,违禁词,屏蔽IP等配置可以说是人性化了,但万一配置不好一些正常评论可能也会被判定为垃圾内容,所以我推荐使用人工审核功能,不过这边不得不说另一个评论系统 <a href="https://twikoo.js.org/">Twikoo</a>,支持查看自己审核中的评论,评论置顶,点赞等,不过我想 Waline 将来也能实现,毕竟 Flag 立那了</p><p>图片上传 uploadImage 部分配置 理论上是可以适配任何图床,配置例子可查看 <a href="https://github.com/lizheming/waline/issues/123">issues/123</a>,当然内置了一个默认图床,开箱即用</p><p>表情配置和之前 Valine 是一样的,同主题还可使用 <code>walien.json</code> 的配置方式,具体可查看<a href="https://butterfly.js.org/posts/ceeb73f/#%E8%A9%95%E8%AB%96">主题文档</a></p><h2 id="CloudBase-云开发部署">CloudBase 云开发部署<a class="fa-solid fa-hashtag" href="#CloudBase-云开发部署"></a></h2><h3 id="一键部署">一键部署<a class="fa-solid fa-hashtag" href="#一键部署"></a></h3><p>一键脚本部署可以查看<a href="https://waline.js.org/server/cloudbase.html">官方文档</a>,我删了之后就没成功过</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612362992018-14b2a225-27d6-4996-948b-e746d26bb2e0.png" alt="" loading="lazy"></p><p>截至文档最新更新日期,这个已被修复(不过tcb-starter那个链接还没改所以还是失败),不过我只能说作者非常不细心,毕竟能一天发十几个版本,详见 <a href="https://github.com/lizheming/waline/commit/d87d3092a34fd6b2b7f0b1c72bd95ad784a086e7">commit</a>,他还是把链接协议头多打了一个 h ,所以请<a href="https://console.cloud.tencent.com/tcb/env/index?action=CreateAndDeployCloudBaseProject&appUrl=https%3A%2F%2Fgithub.com%2Fwalinejs%2Ftcb-starter&branch=master&appName=waline">点击这里</a>一键部署</p><p>嗯,后来修复了,期待接下来的开发</p><hr><p>警告内容来自 <a href="https://twikoo.js.org/quick-start.html">Twikoo 官方文档</a> 建议您直接查看 <a href="#%E6%89%8B%E5%8A%A8%E9%83%A8%E7%BD%B2">手动部署部分</a>!!!</p><p><font style="color:#333333;"><div class="note warning simple"><p></font></p></p><p>一键部署虽然方便,但是仅支持按量计费环境——也就是说,<strong>一键部署的环境,当免费资源用尽后,将会产生费用</strong>。且按量计费环境无法切换为包年包月环境。免费额度数据库读操作数只有 500 次 / 天,<strong>无法支撑 Twikoo 的运行需求</strong>。Twikoo 建议您<a href="#%E6%89%8B%E5%8A%A8%E9%83%A8%E7%BD%B2">手动部署</a>以节约成本。</p><p><font style="color:#333333;"></div></font></p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1610953378969-db93161e-24d3-4a48-8934-5566774b94d2.png" alt="" loading="lazy"></p><p>对于新用户或者说没有创建过按量计费环境的用户会显示如下内容,记得勾选开启免费资源</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1610873567827-825cde85-7c99-4c5a-95e0-44c0966784cb.png" alt="" loading="lazy"></p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612859364523-006d98ba-bd5c-4868-878f-9c9ac158d836.png" alt="" loading="lazy"></p><p>为了日后升级的方便,不管您是否使用了 Vercel 部署,您都可以 fork <a href="https://github.com/ccknbc-actions/waline">我的仓库</a> ,稍加配置即可完成自动部署更新</p><h3 id="手动部署">手动部署<a class="fa-solid fa-hashtag" href="#手动部署"></a></h3><p>首先前往<a href="https://cloud.tencent.com/act/pro/cloudbase01"><strong>腾讯云的活动区域</strong></a>,注册/登陆后往下滑,找到新用户专享云开发标准型(基础版1)资源套餐,0元购买一个免费包年包月环境</p><hr><p>没错,这个环境不错吧</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1610870670315-08e65148-3819-48fb-878e-03fdb0c9ab64.png" alt="" loading="lazy"></p><p>按照提示购买后稍等几分钟,<a href="https://console.cloud.tencent.com/tcb/env/index">在这个界面可查看您所购买的环境</a></p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1610870083481-8e4cad1a-c70a-4cad-9192-11be8003241c.png" alt="" loading="lazy"></p><p>有能力的其实可以看一下 Vercel <a href="#%E8%87%AA%E5%8A%A8%E5%8D%87%E7%BA%A7">自动升级</a>和TCB<a href="#%E8%87%AA%E5%8A%A8%E5%8D%87%E7%BA%A7-1">自动升级</a>部分,间接实现一键部署,自动更新</p><p><a href="https://console.cloud.tencent.com/tcb/scf/index">点击云函数</a>,新建云函数,函数内存选择 128M,名称随意,例如 Waline,其他默认,单击进入下一步</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612359288449-66b53150-2146-4ec9-aa08-910b99aebd1b.png" alt="" loading="lazy"></p><p>下图中的函数代码部分填入以下代码</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612359460424-4b8cf9b4-2ef4-4758-92f6-09ae040a91ea.png" alt="" loading="lazy"></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Tencent is pleased to support the open source community by making CloudBaseFramework - 云原生一体化部署工具 available.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Please refer to license text included with this package for license details.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span>.<span class="property">main</span> = <span class="title function_">async</span> (event, context) => {</span><br><span class="line"> context.<span class="property">callbackWaitsForEmptyEventLoop</span> = <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">const</span> entry = (<span class="function">() =></span> {</span><br><span class="line"> <span class="keyword">const</span> result = <span class="built_in">require</span>(<span class="string">'./app.js'</span>);</span><br><span class="line"> <span class="comment">// const app = require('express')();</span></span><br><span class="line"> <span class="comment">// result = app.use(result);</span></span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> })();</span><br><span class="line"> <span class="keyword">const</span> serverless = <span class="built_in">require</span>(<span class="string">'serverless-http'</span>);</span><br><span class="line"> <span class="keyword">let</span> app = entry;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// support for async load app</span></span><br><span class="line"> <span class="keyword">if</span> (entry && entry.<span class="property">tcbGetApp</span> && <span class="keyword">typeof</span> entry.<span class="property">tcbGetApp</span> === <span class="string">'function'</span>) {</span><br><span class="line"> app = <span class="keyword">await</span> entry.<span class="title function_">tcbGetApp</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">serverless</span>(app, {</span><br><span class="line"> <span class="attr">binary</span>: [</span><br><span class="line"> <span class="string">'application/javascript'</span>,</span><br><span class="line"> <span class="string">'application/json'</span>,</span><br><span class="line"> <span class="string">'application/octet-stream'</span>,</span><br><span class="line"> <span class="string">'application/xml'</span>,</span><br><span class="line"> <span class="string">'font/eot'</span>,</span><br><span class="line"> <span class="string">'font/opentype'</span>,</span><br><span class="line"> <span class="string">'font/otf'</span>,</span><br><span class="line"> <span class="string">'image/*'</span>,</span><br><span class="line"> <span class="string">'video/*'</span>,</span><br><span class="line"> <span class="string">'audio/*'</span>,</span><br><span class="line"> <span class="string">'text/comma-separated-values'</span>,</span><br><span class="line"> <span class="string">'text/css'</span>,</span><br><span class="line"> <span class="string">'text/javascript'</span>,</span><br><span class="line"> <span class="string">'text/plain'</span>,</span><br><span class="line"> <span class="string">'text/text'</span>,</span><br><span class="line"> <span class="string">'text/xml'</span>,</span><br><span class="line"> ],</span><br><span class="line"> })(event, context);</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>点击对应的云函数,进入在线编辑页面,按照<a href="https://github.com/walinejs/tcb-starter">模板仓库</a>里的文件,新建对应的文件,并复制粘贴对应的内容即可</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612360652232-9eb2ad2b-bebe-4964-bb5f-75e2f9946d25.png" alt="" loading="lazy"></p><p>注意点击<strong>保存并安装依赖</strong>,可能会没有反应一会儿,然后等待转圈圈部署完毕即可</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612360855940-241970ec-5c18-4bc8-9168-9fd945deb761.png" alt="" loading="lazy"><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612361085479-f39b6b2b-2293-4685-882e-9e20aa611dea.png" alt="" loading="lazy"></p><p>当然还没有结束,我们需要点击 <code>环境 --> HTTP 访问服务</code> (<a href="https://console.cloud.tencent.com/tcb/env/access">点击直达</a>),如果你想绑定自定义域名可以照图中绑定,记得先申请一下证书,如果你想要 HTTPS(这个可能花的时间有点长)</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612361294908-3ef584b5-5cbc-43e5-b744-cda357057ec0.png" alt="" loading="lazy"></p><p>点击新建,新建触发路径,点击保存即可,注意路径最后没有 / ,等待构建完成后你就可通过对应的链接访问 demo 页面了,这个链接就是上面提到的 <code>serverURL</code> ,例如我的 <a href="https://tcb.ccknbc.cc/waline">https://tcb.ccknbc.cc/waline</a></p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612361631129-fecd45a5-f694-4154-8707-9976eb10adb5.png" alt="" loading="lazy"></p><p>然后我们需要设置<a href="https://console.cloud.tencent.com/tcb/env/safety"> WEB 安全域名</a>,把你的域名放入白名单即可(本地测试的话端口也要对应上哦)</p><h2 id="如何升级">如何升级<a class="fa-solid fa-hashtag" href="#如何升级"></a></h2><h3 id="Vercel">Vercel<a class="fa-solid fa-hashtag" href="#Vercel"></a></h3><h4 id="手动升级">手动升级<a class="fa-solid fa-hashtag" href="#手动升级"></a></h4><p>找到 Vercel 帮你在创建的仓库,叫 <code>waline</code> 啦,编辑 <code>package.json</code> 中依赖版本号即可完成升级,版本号以 <code>npm</code> <img src="https://img.shields.io/npm/v/@waline/vercel?color=critical&logo=npm&style=flat-square" alt="" loading="lazy"><font style="color:#2C3E50;"> 为准,因为 GitHub 由于考虑到电报机器人自动推送消息过于频繁影响到群友,会延迟推送</font></p><h4 id="自动升级">自动升级<a class="fa-solid fa-hashtag" href="#自动升级"></a></h4><p>其实原理还是一样的,因为Vercel会监控仓库文件的变化来帮我们自动部署,那么我们要做的就是自动更改版本号,这里你可以用 <code>Github Actions</code> 实现,定时每隔半小时自动更新并push,但这样似乎有点浪费资源,所以不怎么推荐,而我们这个仓库通常都是公开的(私有也没关系)</p><p>首先你需要安装一个应用<a href="https://github.com/marketplace/renovate">Renovate</a>,选择免费版计划即可,他会帮我们监控所用依赖的版本更新变化,并为提交一个 <code>PR</code> ,我们要做的只是合并 PR 而已,但手动合并之前也讲过,多少有点不方便,自动合并我们知道有打标签自动合并,GitHub Actions 工具人自动合并,这些大家搜以下关键词就好,但这个应用它本身实际上支持自动合并,查看<a href="https://docs.renovatebot.com/configuration-options/#automerge">官方文档</a>发现在 <code>renovate.json</code> 中配置即可,示例代码如下,其中代理人是为了通知更新的作用,与PR同理,但也可删除此段配置,同样的PR也可关闭通知静默自动更新。</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"extends"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="string">"config:base"</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"assignees"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="string">"CCKNBC"</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"separateMinorPatch"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"packageRules"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="punctuation">{</span></span><br><span class="line"> <span class="attr">"updateTypes"</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line"> <span class="string">"minor"</span><span class="punctuation">,</span></span><br><span class="line"> <span class="string">"patch"</span></span><br><span class="line"> <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"automerge"</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line"> <span class="attr">"automergeType"</span><span class="punctuation">:</span> <span class="string">"branch"</span></span><br><span class="line"> <span class="punctuation">}</span></span><br><span class="line"> <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">}</span></span><br></pre></td></tr></table></figure><p>我目前还是用的默认的提交PR自动合并的方式,如果你是公开仓库,还可以使用<a href="https://github.com/marketplace/mergify">Mergify</a>,安装完成后他能它免费帮我们自动合并公开仓库的PR,我们设定一个条件,比如 PR 提交作者为 renovate,就自动帮我们点击合并,并删除多余分支,当然这些都需要配置,这里具体会在另一篇文档中讲到</p><p><font style="color:#333333;"><div class="note info simple"><p></font>以上两个应用你可以选择安装到全部仓库,或者只安装到选择的仓库<font style="color:#333333;"></p></div></font></p><p>如果你想懒的话可以先删除你现有的名为 Waine 的仓库,再 fork <a href="https://github.com/ccknbc-actions/waline">我的仓库</a>,然后去你的 Vercel 解绑之前的仓库,再绑定你fork的仓库,最后点一下重新部署即可</p><p>但是如果你没用tcb 就把 <code>.github/workflows/Update Waline TCB.yml</code> 里的文件删掉,因为涉及到自动部署更新云开发,还有环境变量问题,如果没设定会导致报错</p><h3 id="CloudBase">CloudBase<a class="fa-solid fa-hashtag" href="#CloudBase"></a></h3><hr><h4 id="一键部署-2">一键部署<a class="fa-solid fa-hashtag" href="#一键部署-2"></a></h4><p>就是点击<a href="https://console.cloud.tencent.com/tcb/apps/index">我的应用</a>找到 Waline 点击部署即可</p><p><img src="https://cdn.nlark.com/yuque/0/2021/png/8391407/1612711217029-250d0b1a-75d1-4a7c-9f4c-8a9413ab51fa.png" alt="" loading="lazy"></p><h4 id="手动部署-2">手动部署<a class="fa-solid fa-hashtag" href="#手动部署-2"></a></h4><h5 id="手动升级-2">手动升级<a class="fa-solid fa-hashtag" href="#手动升级-2"></a></h5><p>就是去<a href="https://github.com/walinejs/tcb-starter">仓库</a>复制粘贴修改过的文件的事情了,如果没有文件改动就点击 <code>保存并安装依赖</code> 即可(知道在哪了吧)</p><h5 id="自动升级-2">自动升级<a class="fa-solid fa-hashtag" href="#自动升级-2"></a></h5><p>原理在上面讲了,结合 <a href="#%E8%87%AA%E5%8A%A8%E5%8D%87%E7%BA%A7">Vercel 自动升级</a>部分查看,这部分其实可以作为上面的手动部署,或者自动部署?</p><p>你可以 fork <a href="https://github.com/ccknbc-actions/waline">我的仓库</a> 进行更改,和上面提到的原理差不多,只是用到了 Actions(如果你之前没接触过这些,建议使用 Vercel 部署或者上面的一键部署,也比较方便),在合并PR后帮我们自动升级部署到云开发,解释一下几个密钥,您需要在 仓库的 <code>settings/secrets/actions</code> 中配置,组织的话可以把常用到的密钥添加为组织密钥</p><p>,比如 ID KEY 等</p><table><thead><tr><th>变量名</th><th>变量解释</th></tr></thead><tbody><tr><td><font style="color:#404040;background-color:#FFFFFF;">SECRETID</font></td><td>API 访问密钥 ID,可<a href="https://console.cloud.tencent.com/cam/capi">点击这里</a>新建/查看</td></tr><tr><td><font style="color:#404040;background-color:#FFFFFF;">SECRETKEY</font></td><td><font style="color:#404040;background-color:#FFFFFF;">API 访问密钥 KEY,可</font><a href="https://console.cloud.tencent.com/cam/capi">点击这里</a><font style="color:#404040;background-color:#FFFFFF;">新建/查看</font></td></tr><tr><td>TCBFUNNAME(没什么好加密的,就叫 waline 算了)</td><td>你想要新建/已有函数的名称,比如 <code>Waline</code></td></tr><tr><td>TCBENVID</td><td>环境ID,可<a href="https://console.cloud.tencent.com/tcb/env/overview">点击这里</a>或<a href="https://console.cloud.tencent.com/tcb/env/index">这里</a>查看,地址栏后也会显示,反正就是很多地方都在上面点一下就能看到</td></tr></tbody></table><h2 id="附录">附录<a class="fa-solid fa-hashtag" href="#附录"></a></h2><h3 id="邮件通知模板">邮件通知模板<a class="fa-solid fa-hashtag" href="#邮件通知模板"></a></h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mailSubject</span>: <span class="string">'{{parent.nick}},您在 {{site.name}} 上发表的评论,收到了来自 {{self.nick}} 的回复'</span>,</span><br><span class="line"><span class="attr">mailSubjectAdmin</span>: <span class="string">'{{site.name}} 上收到了来自 {{self.nick}} 的留言'</span>,</span><br><span class="line"><span class="attr">mailTemplate</span>: <span class="string">'<head><base target="_blank"/><style id="scrollbar"type="text/css">::-webkit-scrollbar{width:0!important}pre{white-space:pre-wrap!important;word-wrap:break-word!important;*white-space:normal!important}pre{white-space:pre-wrap!important;word-wrap:break-word!important;*white-space:normal!important}#letter img{max-width:300px}</style><style id="from-wrapstyle"type="text/css">#form-wrap{overflow:hidden;height:447px;position:relative;top:0px;transition:all 1s ease-in-out.3s;z-index:0}</style><style id="from-wraphoverstyle"type="text/css">#form-wrap:hover{height:1300px;top:-200px}</style></head><body><div style="width: 530px;margin: 20px auto 0;height: 1000px;"><div id="form-wrap"><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/before.png"alt="before"style="position: absolute;bottom: 126px;left: 0px;background-repeat: no-repeat;width: 530px;height: 317px;z-index:-100"><div style="position: relative;overflow: visible;height: 1500px;width: 500px;margin: 0px auto;transition: all 1s ease-in-out .3s;padding-top:200px;"<form><div style="background: white;width: 95%;max-width: 800px;margin: auto auto;border-radius: 5px;border: 1px solid;overflow: hidden;-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);"><img style="width:100%;overflow: hidden;"src="https://area.sinaapp.com/bingImg"/><div style="padding: 5px 20px;"><br><div><h3 style="text-decoration: none; color: #8fbc8f;">{{parent.nick}},见信安:</h3></div><br><div id="letter"style="overflow:auto;height:300px;width:100%;display:block;word-break: break-all;word-wrap: break-word;"><p style="display: inline-block;">您在<a style="text-decoration: none;color: #8fbc8f"target="_blank"href="{{site.postUrl}} display: inline-block;">{{site.name}}</a>上发表的评论:</p><div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: "Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">{{parent.comment | safe}}</div><p>收到了来自{{self.nick}}的回复:</p><div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: "Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">{{self.comment | safe}}</div></div><br><div style="text-align: center;margin-top: 40px;"><img src="https://ae01.alicdn.com/kf/U0968ee80fd5c4f05a02bdda9709b041eE.png"alt="hr"style="width:100%; margin:5px auto 5px auto; display: block;"/><a style="text-transform: uppercase;text-decoration: none;font-size: 14px;border: 2px solid #ace0f9;color: #FFFFFF;padding: 10px;display: inline-block;margin: 10px auto 0;background-color: #8fbc8f;"target="_blank"href="{{site.postUrl}}">{{site.name}}|请您签收~</a></div><p style="font-size: 12px;text-align: center;color: #999;">自动书记人偶竭诚为您服务!<br>©2020 - 2021 <a style="text-decoration:none; color:#8fbc8f"href="{{site.url}}">{{site.name}}</a></p></div></div></form></div><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/after.png"alt="after"style=" position: absolute;bottom: -2px;left: 0;background-repeat: no-repeat;width: 530px;height: 259px;z-index:100"></div></div></body>'</span>,</span><br><span class="line"><span class="attr">mailTemplateAdmin</span>: <span class="string">'<head><base target="_blank"/><style id="scrollbar"type="text/css">::-webkit-scrollbar{width:0!important}pre{white-space:pre-wrap!important;word-wrap:break-word!important;*white-space:normal!important}#letter img{max-width:300px}</style><style id="from-wrapstyle"type="text/css">#form-wrap{overflow:hidden;height:447px;position:relative;top:0px;transition:all 1s ease-in-out.3s;z-index:0}</style><style id="from-wraphoverstyle"type="text/css">#form-wrap:hover{height:1300px;top:-200px}</style></head><body><div style="width: 530px;margin: 20px auto 0;height: 1000px;"><div id="form-wrap"><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/before.png"alt="before"style="position: absolute;bottom: 126px;left: 0px;background-repeat: no-repeat;width: 530px;height: 317px;z-index:-100"><div style="position: relative;overflow: visible;height: 1500px;width: 500px;margin: 0px auto;transition: all 1s ease-in-out .3s;padding-top:200px;"><form><div style="background: white;width: 95%;max-width: 800px;margin: auto auto;border-radius: 5px;border: 1px solid;overflow: hidden;-webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);"><img style="width:100%;overflow: hidden;"src="https://area.sinaapp.com/bingImg"/><div style="padding: 5px 20px;"><br><div><h3 style="text-decoration: none; color: #8fbc8f;">来自{{self.nick}}的留言:</h3></div><br><br><div id="letter"style="overflow:auto;height:300px;width:100%;display:block;word-break: break-all;word-wrap: break-word;"><div style="border-bottom: #ddd 1px solid;border-left: #ddd 1px solid;padding-bottom: 20px;background-color: #eee;margin: 15px 0px;padding-left: 20px;padding-right: 20px;border-top: #ddd 1px solid;border-right: #ddd 1px solid;padding-top: 20px;font-family: "Arial", "Microsoft YaHei" , "黑体" , "宋体" , sans-serif;">{{self.comment | safe}}</div></div><div style="text-align: center;margin-top: 40px;"><img src="https://ae01.alicdn.com/kf/U0968ee80fd5c4f05a02bdda9709b041eE.png"alt="hr"style="width:100%; margin:5px auto 5px auto; display: block;"/><a style="text-transform: uppercase;text-decoration: none;font-size: 14px;border: 2px solid #ace0f9;color: #FFFFFF;padding: 10px;display: inline-block;margin: 10px auto 0;background-color: #8fbc8f;"target="_blank"href="{{site.postUrl}}">{{site.name}}|请您过目~</a></div><p style="font-size: 12px;text-align: center;color: #999;">©2020 - 2021 <a style="text-decoration:none; color:#8fbc8f"href="{{site.url}}">{{site.name}}</a></p></div></div></form></div><img src="https://cdn.jsdelivr.net/gh/Akilarlxh/Valine-Admin@v1.0/source/img/after.png"alt="after"style=" position: absolute;bottom: -2px;left: 0;background-repeat: no-repeat;width: 530px;height: 259px;z-index:100"></div></div></body>'</span></span><br></pre></td></tr></table></figure><h3 id="下载">下载<a class="fa-solid fa-hashtag" href="#下载"></a></h3><p><a href="https://file.nmb.show/down.php/4ca88b8fe0729c213cd3a425f87d2f51.rar">邮件通知模板下载</a>(包含 Waline/Valine/Twikoo),您可以下载后根据官方文档提及的变量自行修改<code>index.js</code>相关内容,以上代码仅作参考,对于本文未涉及到的其他内容,请自行查看官方文档,如有错误,欢迎指正,谢谢!</p>]]></c:encoded></item><item><title>GitHub 自动合并 PR 笔记</title><link>https://blog.ccknbc.cc/posts/github-automatically-merges-pull-requests-notes/</link><description>GitHub 自动合并 PR 笔记</description><author>CC康纳百川</author><category domain="https://blog.ccknbc.cc/categories/%E5%B7%A5%E5%85%B7/">工具</category><category domain="https://blog.ccknbc.cc/tags/%E5%B7%A5%E5%85%B7/">工具</category><pubDate>Sat, 22 Aug 2026 16:42:51 GMT</pubDate><c:encoded><</code> (create a merge commit),<br><code>[rebase](https://help.github.com/en/articles/about-pull-request-merges#rebase-and-merge-your-pull-request-commits)</code><br>(rebase all commits of the branch onto the base branch)<br>or <code>[squash](https://help.github.com/en/articles/about-pull-request-merges#squash-and-merge-your-pull-request-commits)</code><br>(squash all commits into a single commit). The default option is <code>merge</code>.</li><li><code>MERGE_METHOD_LABELS</code>: Set to allow labels to determine the merge method<br>(see <code>MERGE_METHOD</code> for possible values).<br>For example, <code>automerge=merge,autosquash=squash</code>. If no such label is present,<br>the method set by <code>MERGE_METHOD</code> will be used. The default value is <code>""</code>.</li><li><code>MERGE_METHOD_LABEL_REQUIRED</code>: Set to <code>true</code> to require one of the<br><code>MERGE_METHOD_LABELS</code> to be set. The default value is <code>false</code>.</li><li><code>MERGE_COMMIT_MESSAGE</code>: The commit message to use when merging the pull<br>request into the base branch. Possible values are <code>automatic</code> (use GitHub’s<br>default message), <code>pull-request-title</code> (use the pull request’s title),<br><code>pull-request-description</code> (use the pull request’s description),<br><code>pull-request-title-and-description</code> or a literal<br>value with optional placeholders (for example <code>Auto merge {pullRequest.number}</code>).<br>The default value is <code>automatic</code>.</li><li><code>MERGE_COMMIT_MESSAGE_REGEX</code>: When using a commit message containing the<br>PR’s body, use the first capturing subgroup from this regex as the commit<br>message. Can be used to separate content that should go with the commit into<br>the code base’s history from boilerplate associated with the PR (licensing<br>notices, check lists, etc). For example, <code>(.*)^---</code> would keep everything up<br>until the first 3-dash line (horizontal rule in MarkDown) from the commit<br>message. The default value is empty, which disables this feature.</li><li><code>MERGE_FILTER_AUTHOR</code>: When set, only pull requests raised by this author<br>will be merged automatically.</li><li><code>MERGE_FORKS</code>: Whether merging from external repositories is enabled<br>or not. By default, pull requests with branches from forked repositories will<br>be merged the same way as pull requests with branches from the main<br>repository. Set this option to <code>false</code> to disable merging of pull requests<br>from forked repositories. The default value is <code>true</code>.</li><li><code>MERGE_RETRIES</code> and <code>MERGE_RETRY_SLEEP</code>: Sometimes, the pull request check<br>runs haven’t finished yet, so the action will retry the merge after some time.<br>The number of retries can be set with <code>MERGE_RETRIES</code>.<br>The default number of retries is <code>6</code> and setting it to <code>0</code> disables the retry logic.<br><code>MERGE_RETRY_SLEEP</code> sets the time to sleep between retries, in milliseconds.<br>The default is <code>5000</code> (5 seconds) and setting it to <code>0</code> disables sleeping<br>between retries.</li><li><code>MERGE_DELETE_BRANCH</code>: Automatic deletion of branches does not work for all<br>repositories. Set this option to <code>true</code> to automatically delete branches<br>after they have been merged. The default value is <code>false</code>.</li></ul><p>The following update options are supported:</p><ul><li><code>UPDATE_LABELS</code>: The labels that need to be present for a pull request to be<br>updated (using <code>UPDATE_METHOD</code>). The default value is <code>automerge</code>.<br>Note that updating will only happen when the option “Require branches to be<br>up to date before merging” is enabled in the branch protection rules.<br>This option can be a comma-separated list of labels, see the <code>MERGE_LABELS</code><br>option for more information.</li><li><code>UPDATE_METHOD</code>: Which method to use when updating the pull request<br>to the base branch. Possible values are <code>merge</code> (create a merge commit) or<br><code>rebase</code> (rebase the branch onto the head of the base branch). The default<br>option is <code>merge</code>.<br>When the option is <code>rebase</code> and the <a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing">rebasing</a><br>failed, the action will exit with error code 1. This will also be visible<br>in the pull request page, with a message like “this branch has conflicts<br>that must be resolved” and a list of conflicting files.</li><li><code>UPDATE_RETRIES</code> and <code>UPDATE_RETRY_SLEEP</code>: Sometimes, the pull request check<br>runs haven’t finished yet and the action doesn’t know if an update is<br>necessary. To query the pull request state multiple times, the number of<br>retries can be set with <code>UPDATE_RETRIES</code>. The default number of retries is <code>1</code><br>and setting it to <code>0</code> disables the retry logic.<br><code>UPDATE_RETRY_SLEEP</code> sets the time to sleep between retries, in milliseconds.<br>The default is <code>5000</code> (5 seconds) and setting it to <code>0</code> disables sleeping<br>between retries.</li></ul><p>Also, the following general options are supported:</p><ul><li><code>GITHUB_TOKEN</code>: This should always be <code>"${{ secrets.GITHUB_TOKEN }}"</code>.<br>However, in some cases it can be useful to run this action as a certain user<br>(by default, it will run as <code>github-actions</code>). This can be useful if you want<br>to use the “Restrict who can push to matching branches” option in the branch<br>protection rules, for example.<br>To use this setting for manually providing a token, you need to create a<br><a href="https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line">personal access token</a><br>for the user (make sure to check <code>public_repo</code> when it’s a public repository<br>or <code>repo</code> when it’s a private repository). All API requests (merge/rebase)<br>will then be executed as the specified user. The token should be kept secret,<br>so make sure to add it as secret, not as environment variable, in the GitHub<br>workflow file!</li></ul><p>You can configure the environment variables in the workflow file like this:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">env:</span></span><br><span class="line"> <span class="attr">GITHUB_TOKEN:</span> <span class="string">"$<span class="template-variable">{{ secrets.GITHUB_TOKEN }}</span>"</span></span><br><span class="line"> <span class="attr">MERGE_LABELS:</span> <span class="string">"automerge,!work in progress"</span></span><br><span class="line"> <span class="attr">MERGE_REMOVE_LABELS:</span> <span class="string">"automerge"</span></span><br><span class="line"> <span class="attr">MERGE_METHOD:</span> <span class="string">"squash"</span></span><br><span class="line"> <span class="attr">MERGE_COMMIT_MESSAGE:</span> <span class="string">"pull-request-description"</span></span><br><span class="line"> <span class="attr">MERGE_FORKS:</span> <span class="string">"false"</span></span><br><span class="line"> <span class="attr">MERGE_RETRIES:</span> <span class="string">"6"</span></span><br><span class="line"> <span class="attr">MERGE_RETRY_SLEEP:</span> <span class="string">"10000"</span></span><br><span class="line"> <span class="attr">UPDATE_LABELS:</span> <span class="string">""</span></span><br><span class="line"> <span class="attr">UPDATE_METHOD:</span> <span class="string">"rebase"</span></span><br></pre></td></tr></table></figure><h2 id="Supported-Events">Supported Events<a class="fa-solid fa-hashtag" href="#Supported-Events"></a></h2><p>Automerge can be configured to run for these events:</p><ul><li><code>check_run</code></li><li><code>check_suite</code></li><li><code>issue_comment</code></li><li><code>pull_request_review</code></li><li><code>pull_request_target</code></li><li><code>pull_request</code></li><li><code>push</code></li><li><code>repository_dispatch</code></li><li><code>schedule</code></li><li><code>status</code></li><li><code>workflow_dispatch</code></li></ul><p>For more information on when these occur, see the Github documentation on <a href="https://docs.github.com/en/actions/reference/events-that-trigger-workflows">events that trigger workflows</a> and <a href="https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads">their payloads</a>.</p><h2 id="Limitations">Limitations<a class="fa-solid fa-hashtag" href="#Limitations"></a></h2><ul><li>When a pull request is merged by this action, the merge will not trigger other GitHub workflows.<br>Similarly, when another GitHub workflow creates a pull request, this action will not be triggered.<br>This is because <a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows">an action in a workflow run can’t trigger a new workflow run</a>. However, the <code>[workflow_run](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#workflow_run)</code> event is triggered as expected.</li><li>When <a href="https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token">using a personal access token (PAT) to work around the above limitation</a>, note that when the user issuing the PAT is an administrator and <a href="https://help.github.com/en/github/administering-a-repository/enabling-branch-restrictions">branch restrictions do not include administrators</a>, pull requests may be merged even if they are not mergeable for non-administrators (see <a href="https://github.com/pascalgn/automerge-action/issues/65">#65</a>).</li><li>Currently, there is no way to trigger workflows when the pull request branch<br>becomes out of date with the base branch. There is a request in the<br><a href="https://github.community/t5/GitHub-Actions/New-Trigger-is-mergable-state/m-p/36908">GitHub community forum</a>.</li></ul><h2 id="Debugging">Debugging<a class="fa-solid fa-hashtag" href="#Debugging"></a></h2><p>To run the action with full debug logging, update your workflow file as follows:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">- name: automerge</span><br><span class="line"> uses: pascalgn/automerge-action@...</span><br><span class="line"> with:</span><br><span class="line"> args: "--trace"</span><br></pre></td></tr></table></figure><p>If you need to further debug the action, you can run it locally.</p><p>You will need a <a href="https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line">personal access token</a>.</p><p>Then clone this repository, create a file <code>.env</code> in the repository, such as:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">GITHUB_TOKEN="123abc..."</span><br><span class="line">URL="https://github.com/pascalgn/repository-name/pull/123"</span><br></pre></td></tr></table></figure><p>Install dependencies with <code>yarn</code>, and finally run <code>yarn it</code> (or <code>npm run it</code>).</p><h2 id="License">License<a class="fa-solid fa-hashtag" href="#License"></a></h2><p><a href="LICENSE">MIT</a></p><h1>bulldozer</h1><p><img src="https://cdn.nlark.com/yuque/0/2021/svg/8391407/1610874951039-f74d3099-f28f-4856-ade7-6c677ce4869d.svg" alt="" loading="lazy"> <img src="https://img.shields.io/docker/pulls/palantirtechnologies/bulldozer.svg" alt="" loading="lazy"></p><p><code>bulldozer</code> is a <a href="https://developer.github.com/apps/">GitHub App</a> that</p><p>automatically merges pull requests (PRs) when (and only when) all required</p><p>status checks are successful and required reviews are provided.</p><p>Additionally, <code>bulldozer</code> can:</p><ul><li>Only merge pull requests that match certain conditions, like having a<br>specific label or comment</li><li>Ignore pull requests that match certain conditions, like having a specific<br>label or comment</li><li>Automatically keep pull request branches up-to-date by merging in the target<br>branch</li><li>Wait for additional status checks that are not required by GitHub</li></ul><p>Bulldozer might be useful if you:</p><ul><li>Have CI builds that take longer than the normal review process. It will merge<br>reviewed PRs as soon as the tests pass so you don’t have to watch the pull<br>request or remember to merge it later.</li><li>Combine it with <a href="https://github.com/palantir/policy-bot">policy-bot</a> to<br>automatically merge certain types of pre-approved or automated changes.</li><li>Want to give contributors more control over when they can merge PRs without<br>granting them write access to the repository.</li><li>Have a lot of active development that makes it difficult to merge a pull<br>request while it is up-to-date with the target branch.</li></ul><h2 id="Contents">Contents<a class="fa-solid fa-hashtag" href="#Contents"></a></h2><ul><li><a href="#behavior">Behavior</a></li><li><a href="#configuration">Configuration</a><ul><li><a href="#bulldozeryml-specification">bulldozer.yml Specification</a></li></ul></li><li><a href="#faq">FAQ</a></li><li><a href="#deployment">Deployment</a></li><li><a href="#development">Development</a></li><li><a href="#contributing">Contributing</a></li><li><a href="#license">License</a></li></ul><h2 id="Behavior">Behavior<a class="fa-solid fa-hashtag" href="#Behavior"></a></h2><p><code>bulldozer</code> will only merge pull requests that GitHub allows non-admin</p><p>collaborators to merge. This means that all branch protection settings,</p><p>including required status checks and required reviews, are respected. It also</p><p>means that you <em>must</em> enable branch protection to prevent <code>bulldozer</code> from</p><p>immediately merging every pull request.</p><p>Only pull requests matching the trigger conditions (or <em>not</em> matching</p><p>ignore conditions) are considered for merging. <code>bulldozer</code> is event-driven,</p><p>which means it will usually merge a pull request within a few seconds of the</p><p>pull request satisfying all preconditions.</p><h2 id="Configuration-2">Configuration<a class="fa-solid fa-hashtag" href="#Configuration-2"></a></h2><p>The behavior of the bot is configured by a <code>.bulldozer.yml</code> file at the root of</p><p>the repository. The file name and location are configurable when running your</p><p>own instance of the server.</p><p>The <code>.bulldozer.yml</code> file is read from the most recent commit on the target</p><p>branch of each pull request. If <code>bulldozer</code> cannot find a configuration file,</p><p>it will take no action. This means it is safe to enable the <code>bulldozer</code> on all</p><p>repositories in an organization.</p><h3 id="bulldozer-yml-Specification">bulldozer.yml Specification<a class="fa-solid fa-hashtag" href="#bulldozer-yml-Specification"></a></h3><p>The <code>.bulldozer.yml</code> file supports the following keys.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># "version" is the configuration version, currently "1".</span></span><br><span class="line"><span class="attr">version:</span> <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># "merge" defines how and when pull requests are merged. If the section is</span></span><br><span class="line"><span class="comment"># missing, bulldozer will consider all pull requests and use default settings.</span></span><br><span class="line"><span class="attr">merge:</span></span><br><span class="line"> <span class="comment"># "trigger" defines the set of pull requests considered by bulldozer. If</span></span><br><span class="line"> <span class="comment"># the section is missing, bulldozer considers all pull requests not excluded</span></span><br><span class="line"> <span class="comment"># by the ignore conditions.</span></span><br><span class="line"> <span class="attr">trigger:</span></span><br><span class="line"> <span class="comment"># Pull requests with any of these labels (case-insensitive) are added to</span></span><br><span class="line"> <span class="comment"># the trigger.</span></span><br><span class="line"> <span class="attr">labels:</span> [<span class="string">"merge when ready"</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Pull requests where the body or any comment contains any of these</span></span><br><span class="line"> <span class="comment"># substrings are added to the trigger.</span></span><br><span class="line"> <span class="attr">comment_substrings:</span> [<span class="string">"==MERGE_WHEN_READY=="</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Pull requests where any comment matches one of these exact strings are</span></span><br><span class="line"> <span class="comment"># added to the trigger.</span></span><br><span class="line"> <span class="attr">comments:</span> [<span class="string">"Please merge this pull request!"</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Pull requests where the body contains any of these substrings are added</span></span><br><span class="line"> <span class="comment"># to the trigger.</span></span><br><span class="line"> <span class="attr">pr_body_substrings:</span> [<span class="string">"==MERGE_WHEN_READY=="</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Pull requests targeting any of these branches are added to the trigger.</span></span><br><span class="line"> <span class="attr">branches:</span> [<span class="string">"develop"</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Pull requests targeting branches matching any of these regular expressions are added to the trigger.</span></span><br><span class="line"> <span class="attr">branch_patterns:</span> [<span class="string">"feature/.*"</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># "ignore" defines the set of pull request ignored by bulldozer. If the</span></span><br><span class="line"> <span class="comment"># section is missing, bulldozer considers all pull requests. It takes the</span></span><br><span class="line"> <span class="comment"># same keys as the "trigger" section.</span></span><br><span class="line"> <span class="attr">ignore:</span></span><br><span class="line"> <span class="attr">labels:</span> [<span class="string">"do not merge"</span>]</span><br><span class="line"> <span class="attr">comment_substrings:</span> [<span class="string">"==DO_NOT_MERGE=="</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># "method" defines the merge method. The available options are "merge",</span></span><br><span class="line"> <span class="comment"># "rebase", "squash", and "ff-only".</span></span><br><span class="line"> <span class="attr">method:</span> <span class="string">squash</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Allows the merge method that is used when auto-merging a PR to be different based on the</span></span><br><span class="line"> <span class="comment"># target branch. The keys of the hash are the target branch name, and the values are the merge method that</span></span><br><span class="line"> <span class="comment"># will be used for PRs targeting that branch. The valid values are the same as for the "method" key.</span></span><br><span class="line"> <span class="comment"># <span class="doctag">Note:</span> If the target branch does not match any of the specified keys, the "method" key is used instead.</span></span><br><span class="line"> <span class="attr">branch_method:</span></span><br><span class="line"> <span class="attr">develop:</span> <span class="string">squash</span></span><br><span class="line"> <span class="attr">master:</span> <span class="string">merge</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># "options" defines additional options for the individual merge methods.</span></span><br><span class="line"> <span class="attr">options:</span></span><br><span class="line"> <span class="comment"># "squash" options are only used when the merge method is "squash"</span></span><br><span class="line"> <span class="attr">squash:</span></span><br><span class="line"> <span class="comment"># "title" defines how the title of the commit message is created when</span></span><br><span class="line"> <span class="comment"># generating a squash commit. The options are "pull_request_title",</span></span><br><span class="line"> <span class="comment"># "first_commit_title", and "github_default_title". The default is</span></span><br><span class="line"> <span class="comment"># "pull_request_title".</span></span><br><span class="line"> <span class="attr">title:</span> <span class="string">"pull_request_title"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># "body" defines how the body of the commit message is created when</span></span><br><span class="line"> <span class="comment"># generating a squash commit. The options are "pull_request_body",</span></span><br><span class="line"> <span class="comment"># "summarize_commits", and "empty_body". The default is "empty_body".</span></span><br><span class="line"> <span class="attr">body:</span> <span class="string">"empty_body"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># If "body" is "pull_request_body", then the commit message will be the</span></span><br><span class="line"> <span class="comment"># part of the pull request body surrounded by "message_delimiter"</span></span><br><span class="line"> <span class="comment"># strings. This is disabled (empty string) by default.</span></span><br><span class="line"> <span class="attr">message_delimiter:</span> <span class="string">==COMMIT_MSG==</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># "required_statuses" is a list of additional status contexts that must pass</span></span><br><span class="line"> <span class="comment"># before bulldozer can merge a pull request. This is useful if you want to</span></span><br><span class="line"> <span class="comment"># require extra testing for automated merges, but not for manual merges.</span></span><br><span class="line"> <span class="attr">required_statuses:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">"ci/circleci: ete-tests"</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># If true, bulldozer will delete branches after their pull requests merge.</span></span><br><span class="line"> <span class="attr">delete_after_merge:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># "update" defines how and when to update pull request branches. Unlike with</span></span><br><span class="line"><span class="comment"># merges, if this section is missing, bulldozer will not update any pull requests.</span></span><br><span class="line"><span class="attr">update:</span></span><br><span class="line"> <span class="comment"># "trigger" defines the set of pull requests that should be updated by</span></span><br><span class="line"> <span class="comment"># bulldozer. It accepts the same keys as the trigger in the "merge" block.</span></span><br><span class="line"> <span class="attr">trigger:</span></span><br><span class="line"> <span class="attr">labels:</span> [<span class="string">"WIP"</span>, <span class="string">"Update Me"</span>]</span><br><span class="line"></span><br><span class="line"> <span class="comment"># "ignore" defines the set of pull requests that should not be updated by</span></span><br><span class="line"> <span class="comment"># bulldozer. It accepts the same keys as the ignore in the "merge" block.</span></span><br><span class="line"> <span class="attr">ignore:</span></span><br><span class="line"> <span class="attr">labels:</span> [<span class="string">"Do Not Update"</span>]</span><br></pre></td></tr></table></figure><h2 id="FAQ">FAQ<a class="fa-solid fa-hashtag" href="#FAQ"></a></h2><h4 id="Can-I-specify-both-ignore-and-trigger">Can I specify both <code>ignore</code> and <code>trigger</code>?<a class="fa-solid fa-hashtag" href="#Can-I-specify-both-ignore-and-trigger"></a></h4><p>Yes. If both <code>ignore</code> and <code>trigger</code> are specified, bulldozer will attempt to match</p><p>on both. In cases where both match, <code>ignore</code> will take precedence.</p><h4 id="Can-I-specify-the-body-of-the-commit-when-using-the-squash-strategy">Can I specify the body of the commit when using the <code>squash</code> strategy?<a class="fa-solid fa-hashtag" href="#Can-I-specify-the-body-of-the-commit-when-using-the-squash-strategy"></a></h4><p>Yes. When the merge strategy is <code>squash</code>, you can set additional options under the</p><p><code>options.squash</code> property, including how to render the commit body.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">merge:</span></span><br><span class="line"> <span class="attr">method:</span> <span class="string">squash</span></span><br><span class="line"> <span class="attr">options:</span></span><br><span class="line"> <span class="attr">squash:</span></span><br><span class="line"> <span class="attr">body:</span> <span class="string">summarize_commits</span> <span class="comment"># or `pull_request_body`, `empty_body`</span></span><br></pre></td></tr></table></figure><p>You can also define part of pull request body to pick as a commit message when</p><p><code>body</code> is <code>pull_request_body</code>.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">merge:</span></span><br><span class="line"> <span class="attr">method:</span> <span class="string">squash</span></span><br><span class="line"> <span class="attr">options:</span></span><br><span class="line"> <span class="attr">squash:</span></span><br><span class="line"> <span class="attr">body:</span> <span class="string">pull_request_body</span></span><br><span class="line"> <span class="attr">message_delimiter:</span> <span class="string">==COMMIT_MSG==</span></span><br></pre></td></tr></table></figure><p>Anything that’s contained between two <code>==COMMIT_MSG==</code> strings will become the</p><p>commit message instead of whole pull request body.</p><h4 id="What-if-I-don’t-want-to-put-config-files-into-each-repo">What if I don’t want to put config files into each repo?<a class="fa-solid fa-hashtag" href="#What-if-I-don’t-want-to-put-config-files-into-each-repo"></a></h4><p>You can add default repository configuration in your bulldozer config file.</p><p>It will be used only when your repo config file does not exist.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">options:</span></span><br><span class="line"> <span class="attr">default_repository_config:</span></span><br><span class="line"> <span class="attr">ignore:</span></span><br><span class="line"> <span class="attr">labels:</span> [<span class="string">"do not merge"</span>] <span class="comment"># or any other available config.</span></span><br></pre></td></tr></table></figure><h4 id="Bulldozer-isn’t-merging-my-commit-when-it-should-what-could-be-happening">Bulldozer isn’t merging my commit when it should, what could be happening?<a class="fa-solid fa-hashtag" href="#Bulldozer-isn’t-merging-my-commit-when-it-should-what-could-be-happening"></a></h4><p>Bulldozer will attempt to merge a branch whenever it passes the trigger/ignore</p><p>criteria. GitHub may prevent it from merging a branch in certain conditions, some of</p><p>which are to be expected, and others that may be caused by mis-configuring Bulldozer.</p><ul><li>Required status checks have not passed</li><li>Review requirements are not satisfied</li><li>The merge strategy configured in <code>.bulldozer.yml</code> is not allowed by your<br>repository settings</li><li>Branch protection rules are preventing <code>bulldozer[bot]</code> from <a href="https://help.github.com/articles/about-branch-restrictions/">pushing to the<br>branch</a>. Github apps can be added to the list of restricted<br>push users, so you can allow Bulldozer specifically for your repo.</li></ul><h4 id="Bulldozer-isn’t-updating-my-branch-when-it-should-what-could-be-happening">Bulldozer isn’t updating my branch when it should, what could be happening?<a class="fa-solid fa-hashtag" href="#Bulldozer-isn’t-updating-my-branch-when-it-should-what-could-be-happening"></a></h4><p>When using the branch update functionality, Bulldozer only acts when the target</p><p>branch is updated <em>after</em> updates are enabled for the pull request. For</p><p>example:</p><ol><li>User A opens a pull request targetting <code>develop</code></li><li>User B pushes a commit to <code>develop</code></li><li>User A adds the <code>update me</code> label to the first pull request</li><li>User C pushes a commit to <code>develop</code></li><li>Bulldozer updates the pull request with the commits from Users B and C</li></ol><p>Note that the update does <em>not</em> happen when the <code>update me</code> label is added,</p><p>even though there is a new commit on <code>develop</code> that is not part of the pull</p><p>request.</p><h4 id="Can-Bulldozer-work-with-push-restrictions-on-branches">Can Bulldozer work with push restrictions on branches?<a class="fa-solid fa-hashtag" href="#Can-Bulldozer-work-with-push-restrictions-on-branches"></a></h4><p>As mentioned above, as of Github ~2.19.x, GitHub Apps <em>can</em> be added to the list of users associated</p><p>with <a href="https://help.github.com/articles/about-branch-restrictions/">push restrictions</a>. If you don’t want to do this, or if you’re running</p><p>an older version of Github that doesn’t support this behaviour, you may work</p><p>around this:</p><ol><li>Use another app like <a href="https://github.com/palantir/policy-bot">policy-bot</a> to<br>implement <em>approval</em> restrictions as required status checks instead of using<br>push restrictions. This effectively limits who can push to a branch by<br>requiring changes to go through the pull request process and be approved.</li><li>Configure Bulldozer to use a personal access token for a regular user to<br>perform merges in this case. The token must have the <code>repo</code> scope and the<br>user must be allowed to push to the branch. In the server configuration<br>file, set:</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">options:</span></span><br><span class="line"> <span class="attr">push_restriction_user_token:</span> <span class="string"><token-value></span></span><br></pre></td></tr></table></figure><ol start="2"><li>The token is <em>only</em> used if the target branch has push restrictions enabled.<br>All other merges are performed as the normal GitHub App user.</li></ol><h2 id="Deployment">Deployment<a class="fa-solid fa-hashtag" href="#Deployment"></a></h2><p>bulldozer is easy to deploy in your own environment as it has no dependencies</p><p>other than GitHub. It is also safe to run multiple instances of the server,</p><p>making it a good fit for container schedulers like Nomad or Kubernetes.</p><p>We provide both a Docker container and a binary distribution of the server:</p><ul><li>Binaries: <a href="https://bintray.com/palantir/releases/bulldozer">https://bintray.com/palantir/releases/bulldozer</a></li><li>Docker Images: <a href="https://hub.docker.com/r/palantirtechnologies/bulldozer/">https://hub.docker.com/r/palantirtechnologies/bulldozer/</a></li></ul><p>A sample configuration file is provided at <code>config/bulldozer.example.yml</code>.</p><p>Certain values may also be set by environment variables; these are noted in the</p><p>comments in the sample configuration file.</p><h3 id="GitHub-App-Configuration">GitHub App Configuration<a class="fa-solid fa-hashtag" href="#GitHub-App-Configuration"></a></h3><p>To configure Bulldozer as a GitHub App, these general options are required:</p><ul><li><strong>Webhook URL</strong>: <code>http(s)://<your-bulldozer-domain>/api/github/hook</code></li><li><strong>Webhook secret</strong>: A random string that matches the value of the<br><code>github.app.webhook_secret</code> property in the server configuration</li></ul><p>The app requires these permissions:</p><table><thead><tr><th>Permission</th><th>Access</th><th>Reason</th></tr></thead><tbody><tr><td>Repository administration</td><td>Read-only</td><td>Determine required status checks</td></tr><tr><td>Checks</td><td>Read-only</td><td>Read checks for ref</td></tr><tr><td>Repository contents</td><td>Read & write</td><td>Read configuration, perform merges</td></tr><tr><td>Issues</td><td>Read & write</td><td>Read comments, close linked issues</td></tr><tr><td>Repository metadata</td><td>Read-only</td><td>Basic repository data</td></tr><tr><td>Pull requests</td><td>Read & write</td><td>Merge and close pull requests</td></tr><tr><td>Commit status</td><td>Read-only</td><td>Evaluate pull request status</td></tr></tbody></table><p>The app should be subscribed to these events:</p><ul><li>Check run</li><li>Commit comment</li><li>Pull request</li><li>Status</li><li>Push</li><li>Issue comment</li><li>Pull request review</li><li>Pull request review comment</li></ul><h3 id="Operations">Operations<a class="fa-solid fa-hashtag" href="#Operations"></a></h3><p>bulldozer uses <a href="https://github.com/palantir/go-baseapp">go-baseapp</a> and</p><p><a href="https://github.com/palantir/go-githubapp">go-githubapp</a>, both of which emit</p><p>standard metrics and structured log keys. Please see those projects for</p><p>details.</p><h3 id="Example-Files">Example Files<a class="fa-solid fa-hashtag" href="#Example-Files"></a></h3><p>Example <code>.bulldozer.yml</code> files can be found in <code>[config/examples](https://github.com/palantir/bulldozer/tree/develop/config/examples)</code></p><h3 id="Migrating-Version-0-4-X-to-1-X">Migrating: Version 0.4.X to 1.X<a class="fa-solid fa-hashtag" href="#Migrating-Version-0-4-X-to-1-X"></a></h3><p>The server configuration for bulldozer allows you to specify <code>configuration_v0_path</code>, which is a list of paths</p><p>to check for <code>0.4.X</code> style bulldozer configuration. When a <code>1.X</code> style configuration file does not appear</p><p>at the configured path, bulldozer will attempt to read from the paths configured by <code>configuration_v0_path</code>,</p><p>converting the legacy configuration into an equivalent <code>v1</code> configuration internally.</p><p>The upgrade process is therefore to deploy the latest version of bulldozer with both <code>configuration_path</code> and</p><p><code>configuration_v0_path</code> configured, and to enable the bulldozer GitHub App on all organizations where it was</p><p>previously installed.</p><h2 id="Development">Development<a class="fa-solid fa-hashtag" href="#Development"></a></h2><p>To develop <code>bulldozer</code>, you will need a <a href="https://golang.org/doc/install">Go installation</a>.</p><p><strong>Run style checks and tests</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./godelw verify</span><br></pre></td></tr></table></figure><p><strong>Running the server locally</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># copy and edit the server config</span><br><span class="line">cp config/bulldozer.example.yml config/bulldozer.yml</span><br><span class="line"></span><br><span class="line">./godelw run bulldozer server</span><br></pre></td></tr></table></figure><ul><li><code>config/bulldozer.yml</code> is used as the default configuration file</li><li>The server is available at <code>http://localhost:8080/</code></li></ul><p><strong>Running the server via Docker</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># copy and edit the server config</span><br><span class="line">cp config/bulldozer.example.yml config/bulldozer.yml</span><br><span class="line"></span><br><span class="line"># build the docker image</span><br><span class="line">./godelw docker build --verbose</span><br><span class="line"></span><br><span class="line">docker run --rm -v "$(pwd)/config:/secrets/" -p 8080:8080 palantirtechnologies/bulldozer:latest</span><br></pre></td></tr></table></figure><ul><li>This mounts the <code>config</code> directory (which should contain the <code>bulldozer.yml</code> configuration file) at the expected location</li><li>The server is available at <code>http://localhost:8080/</code></li></ul><h2 id="Contributing">Contributing<a class="fa-solid fa-hashtag" href="#Contributing"></a></h2><p>Contributions and issues are welcome. For new features or large contributions,</p><p>we prefer discussing the proposed change on a GitHub issue prior to a PR.</p><h2 id="License-2">License<a class="fa-solid fa-hashtag" href="#License-2"></a></h2><p>This application is made available under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>.</p><h1>probot-auto-merge</h1><p><img src="https://travis-ci.org/bobvanderlinden/probot-auto-merge.svg?branch=master" alt="" loading="lazy"></p><p><img src="https://img.shields.io/coveralls/github/bobvanderlinden/probot-auto-merge.svg" alt="" loading="lazy"></p><p>A GitHub App built with <a href="https://github.com/probot/probot">Probot</a> that automatically merges PRs</p><blockquote><p><img src="/" alt="" loading="lazy"></p></blockquote><h2 id="Usage-2">Usage<a class="fa-solid fa-hashtag" href="#Usage-2"></a></h2><ol><li><a href="https://github.com/apps/probot-auto-merge">Configure the GitHub App</a></li><li>Create <code>.github/auto-merge.yml</code> in your repository.</li><li>Customize configuration to your needs. See below.</li></ol><h2 id="Configuration-3">Configuration<a class="fa-solid fa-hashtag" href="#Configuration-3"></a></h2><p>Configuration of <code>probot-auto-merge</code> is done through <code>.github/auto-merge.yml</code> in</p><p>your repository. An example of this file can be found <a href="auto-merge.example.yml">here</a>.</p><p>You can also see the configuration for this repository <a href=".github/auto-merge.yml">here</a>.</p><p>The configuration has values that serve as conditions on whether or not a pull request</p><p>should be automatically merged and also configuration about the merge itself. Values</p><p>that serve as conditions are annotated as such below.</p><p>All conditions must be met before a PR will be automatically merged. You can get more</p><p>flexibility by defining multiple rules. Rules can have multiple conditions and if any</p><p>of the conditions inside a rule are met, the PR is also merged. See <a href="#rules-default-none">rules</a>.</p><p>If the target branch is a protected branch, you must add <code>probot-auto-merge</code> bot to</p><p>the list of <code>People, teams or apps with push access</code> in your branch protection rules.</p><p>Note that the default configuration options are to do nothing. This is to prevent</p><p>implicit and possibly unintended behavior.</p><p>The configuration fields are as follows:</p><h3 id="minApprovals-required-condition"><code>minApprovals</code> (required, condition)<a class="fa-solid fa-hashtag" href="#minApprovals-required-condition"></a></h3><p>The minimum number of reviews from each association that approve the pull request before</p><p>doing an automatic merge. For more information about associations see:</p><p><a href="https://developer.github.com/v4/enum/commentauthorassociation/">https://developer.github.com/v4/enum/commentauthorassociation/</a></p><p>Possible associations: <code>OWNER</code>, <code>MEMBER</code>, <code>COLLABORATOR</code>, <code>CONTRIBUTOR</code>, <code>FIRST_TIMER</code>, <code>FIRST_TIME_CONTRIBUTOR</code>, <code>NONE</code></p><p>In the example below when a pull request gets 2 approvals from owners, members or collaborators,</p><p>the automatic merge will continue.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">minApprovals:</span></span><br><span class="line"> <span class="attr">COLLABORATOR:</span> <span class="number">2</span></span><br></pre></td></tr></table></figure><p>In the example below when a pull request gets 1 approval from an owner OR 2 approvals from members, the automatic merge will continue.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">minApprovals:</span></span><br><span class="line"> <span class="attr">OWNER:</span> <span class="number">1</span></span><br><span class="line"> <span class="attr">MEMBER:</span> <span class="number">2</span></span><br></pre></td></tr></table></figure><h3 id="requiredReviewers-condition-default-none"><code>requiredReviewers</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#requiredReviewers-condition-default-none"></a></h3><p>Whenever required reviewers are configured, pull requests will only be automatically</p><p>merged whenever all of these reviewers have approved the pull request.</p><p>In the example below, pull requests need to have been approved by the user ‘rogerluan’</p><p>before they will be automatically merged.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">requiredReviewers:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">rogerluan</span></span><br></pre></td></tr></table></figure><h3 id="maxRequestedChanges-condition-default-none"><code>maxRequestedChanges</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#maxRequestedChanges-condition-default-none"></a></h3><p>Similar to <code>minApprovals</code>, maxRequestedChanges determines the maximum number of</p><p>requested changes before a pull request will be blocked from being automatically</p><p>merged.</p><p>It yet again allows you to configure this per association.</p><p>Note that <code>maxRequestedChanges</code> takes precedence over <code>minApprovals</code>.</p><p>In the example below, automatic merges will be blocked when one of the owners, members</p><p>or collaborators has requested changes.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">maxRequestedChanges:</span></span><br><span class="line"> <span class="attr">COLLABORATOR:</span> <span class="number">0</span></span><br></pre></td></tr></table></figure><p>In the example below, automatic merges will be blocked when the owner has</p><p>requested changes or two members, collaborators or other users have requested</p><p>changes.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">maxRequestedChanges:</span></span><br><span class="line"> <span class="attr">OWNER:</span> <span class="number">0</span></span><br><span class="line"> <span class="attr">NONE:</span> <span class="number">1</span></span><br></pre></td></tr></table></figure><p>The default for this value is:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">maxRequestedChanges:</span></span><br><span class="line"> <span class="attr">NONE:</span> <span class="number">0</span></span><br></pre></td></tr></table></figure><h3 id="blockingBaseBranches-condition-default-none"><code>blockingBaseBranches</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#blockingBaseBranches-condition-default-none"></a></h3><p>Whenever blocking base branches are configured, pull requests will only be automatically</p><p>merged whenever their base branch (into which the PR would be merged) is not matching</p><p>the patterns listed.</p><p>In the example below, pull requests that have the base branch <code>develop</code> or one that starts</p><p>with <code>feature-</code> will not be merged automatically.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">blockingBaseBranches:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">develop</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">regex:</span> <span class="string">^feature-</span></span><br></pre></td></tr></table></figure><p>Note: remove the whole section when you’re not using blocking base branches.</p><h3 id="requiredBaseBranches-condition-default-none"><code>requiredBaseBranches</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#requiredBaseBranches-condition-default-none"></a></h3><p>Whenever required base branches are configured, pull requests will only be automatically</p><p>merged whenever their base branch (into which the PR would be merged) is matching</p><p>any of the patterns listed.</p><p>In the example below, pull requests need to have the base branch <code>master</code> or one that</p><p>starts with <code>v{number}</code> before they will be automatically merged.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">requiredBaseBranches:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">master</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">regex:</span> <span class="string">^v\d</span></span><br></pre></td></tr></table></figure><h3 id="blockingLabels-condition-default-none"><code>blockingLabels</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#blockingLabels-condition-default-none"></a></h3><p>Blocking labels are the labels that can be attached to a pull request to make</p><p>sure the pull request is not being merged automatically.</p><p>In the example below, pull requests that have the <code>blocked</code> label will not be</p><p>merged automatically.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">blockingLabels:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">blocked</span></span><br></pre></td></tr></table></figure><p>The above example denotes literal label names. Regular expressions can be used to</p><p>partially match labels. This can be specified by the <code>regex:</code> property in the</p><p>configuration. The following example will block merging when a label is added that</p><p>starts with the text <code>blocked</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">blockingLabels:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">regex:</span> <span class="string">^blocked</span></span><br></pre></td></tr></table></figure><p>Note: remove the whole section when you’re not using blocking labels.</p><h3 id="requiredLabels-condition-default-none"><code>requiredLabels</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#requiredLabels-condition-default-none"></a></h3><p>Whenever required labels are configured, pull requests will only be automatically</p><p>merged whenever all of these labels are attached to a pull request.</p><p>In the example below, pull requests need to have the label <code>merge</code> before they</p><p>will be automatically merged.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">requiredLabels:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">merge</span></span><br></pre></td></tr></table></figure><p>The above example denotes literal label names. Regular expressions can be used to</p><p>partially match labels. This requires <code>regex:</code> property in the configuration. The</p><p>following example will requires at least one label that starts with <code>merge</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">requiredLabels:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">regex:</span> <span class="string">^merge</span></span><br></pre></td></tr></table></figure><p>Note: remove the whole section when you’re not using required labels.</p><h3 id="blockingTitleRegex-condition-default-none"><code>blockingTitleRegex</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#blockingTitleRegex-condition-default-none"></a></h3><p>Whenever a blocking title regular expression is configured, pull requests that have a title</p><p>matching the configured expression will not be automatically merged.</p><p>This is useful whenever pull requests with <code>WIP</code> in their title need to be skipped.</p><p>In the example below, pull requests with the word <code>wip</code> in the title will not be</p><p>automatically merged. This also includes <code>[wip]</code>, <code>WIP</code> or <code>[WIP]</code>, but not <code>swiping</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">blockingTitleRegex:</span> <span class="string">'\bWIP\b'</span></span><br></pre></td></tr></table></figure><h3 id="requiredTitleRegex-condition-default-none"><code>requiredTitleRegex</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#requiredTitleRegex-condition-default-none"></a></h3><p>Whenever a required title regular expression is configured, only pull requests that have a title</p><p>matching the configured expression will automatically be merged.</p><p>This is useful for forks, that can only create pull request text, no labels.</p><p>In the example below, pull requests with the title containing <code>MERGE</code> will be</p><p>automatically merged. This also includes This also includes <code>[merge]</code>, <code>MERGE</code> or <code>[MERGE]</code>, but not <code>submerge</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">requiredTitleRegex:</span> <span class="string">'\bMERGE\b'</span></span><br></pre></td></tr></table></figure><h3 id="blockingBodyRegex-condition-default-none"><code>blockingBodyRegex</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#blockingBodyRegex-condition-default-none"></a></h3><p>Whenever a blocking body regular expression is configured, pull requests that have a body</p><p>matching the configured expression will not be automatically merged.</p><p>This is useful whenever pull requests with a certain string in their body need to be skipped.</p><p>In the example below, pull requests with the body containing <code>do-not-merge</code> will not be</p><p>automatically merged. This also includes <code>labels: do-not-merge</code>, <code>LABELS: DO-NOT-MERGE</code> or <code>some more text, but do-not-merge</code>,</p><p>but not <code>do-not-merge-just-kidding</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">blockingBodyRegex:</span> <span class="string">'(^|\\s)do-not-merge($|\\s)'</span></span><br></pre></td></tr></table></figure><h3 id="requiredBodyRegex-condition-default-none"><code>requiredBodyRegex</code> (condition, default: none)<a class="fa-solid fa-hashtag" href="#requiredBodyRegex-condition-default-none"></a></h3><p>Whenever a required body regular expression is configured, only pull requests that have a body</p><p>matching the configured expression will automatically be merged.</p><p>This is useful for forks, that can only create pull request text, no labels.</p><p>In the example below, pull requests with the body containing <code>ok-to-merge</code> will be</p><p>automatically merged. This also includes <code>labels: ok-to-merge</code>, <code>LABELS: OK-TO-MERGE</code> or <code>some more text, but ok-to-merge</code>, but not <code>not-ok-to-merge</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">requiredBodyRegex:</span> <span class="string">'(^|\\s)ok-to-merge($|\\s)'</span></span><br></pre></td></tr></table></figure><h3 id="reportStatus-default-false"><code>reportStatus</code> (default: <code>false</code>)<a class="fa-solid fa-hashtag" href="#reportStatus-default-false"></a></h3><p>The status of the auto-merge process will be shown in each PR as a <a href="https://help.github.com/articles/about-status-checks/">check</a>. This can be especially useful to find out why a PR is not being merged automatically.</p><p>To enable status reporting, add the following to your configuration:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">reportStatus:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h3 id="updateBranch-default-false"><code>updateBranch</code> (default: <code>false</code>)<a class="fa-solid fa-hashtag" href="#updateBranch-default-false"></a></h3><p>Whether an out-of-date pull request is automatically updated.</p><p>It does so by merging its base on top of the head of the pull request.</p><p>This is similar to the behavior of the ‘Update branch’ button.</p><p><code>updateBranch</code> is useful for repositories where protected branches are used</p><p>and the option <em>Require branches to be up to date before merging</em> is enabled.</p><p>Note that this only works when the branch of the pull request resides in the same</p><p>repository as the pull request itself.</p><p>In the example below automatic updating of branches is enabled:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">updateBranch:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h3 id="deleteBranchAfterMerge-default-false"><code>deleteBranchAfterMerge</code> (default: <code>false</code>)<a class="fa-solid fa-hashtag" href="#deleteBranchAfterMerge-default-false"></a></h3><p>Whether the pull request branch is automatically deleted.</p><p>This is the equivalent of clicking the ‘Delete branch’ button shown on merged</p><p>pull requests.</p><p>Note that this only works when the branch of the pull request resides in the same</p><p>repository as the pull request itself.</p><p>In the example below automatic deletion of pull request branches is enabled:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deleteBranchAfterMerge:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><h3 id="mergeMethod-default-merge"><code>mergeMethod</code> (default: <code>merge</code>)<a class="fa-solid fa-hashtag" href="#mergeMethod-default-merge"></a></h3><p>In what way a pull request is merged. This can be:</p><ul><li><code>merge</code>: creates a merge commit, combining the commits from the pull request on top of<br>the base of the pull request (default)</li><li><code>rebase</code>: places the commits from the pull request individually on top of the base of the pull request</li><li><code>squash</code>: combines all changes from the pull request into a single commit and places the commit on top<br>of the base of the pull request</li></ul><p>For more information see <a href="https://help.github.com/articles/about-pull-request-merges/">https://help.github.com/articles/about-pull-request-merges/</a></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mergeMethod:</span> <span class="string">merge</span></span><br></pre></td></tr></table></figure><h3 id="mergeCommitMessage-default-none"><code>mergeCommitMessage</code> (default: none)<a class="fa-solid fa-hashtag" href="#mergeCommitMessage-default-none"></a></h3><p>Optionally specify the merge commit message format. The following template tags</p><p>are supported:</p><ul><li><code>{title}</code>: The pull request title at the moment it is merged</li><li><code>{body}</code>: The pull request body at the moment it is merged</li><li><code>{number}</code>: The pull request number</li><li><code>{branch}</code>: The name of the source branch</li><li><code>{commits}</code>: A list of merged commits</li></ul><p>When this option is not set, the merge commit message is controlled by</p><p>GitHub and uses a combination of the title of the pull request when it was</p><p>opened (note that later changes to the title are ignored) and a list of</p><p>commits.</p><p>This settings is ignored when <code>mergeMethod</code> is set to <code>rebase</code>.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mergeCommitMessage:</span> <span class="string">|</span></span><br><span class="line"><span class="string"> {title} (#{number})</span></span><br><span class="line"><span class="string"> {body}</span></span><br></pre></td></tr></table></figure><h3 id="rules-default-none"><code>rules</code> (default: none)<a class="fa-solid fa-hashtag" href="#rules-default-none"></a></h3><p>Rules allow more flexibility configuring conditions for automatically merging. Each rule is defined by</p><p>multiple conditions. All conditions inside a rule must be met before a rule triggers a merge. Any of the</p><p>defined rules can trigger a merge individually.</p><p>An example of a configuration with 2 rules that will trigger a merge upon 1 approval from an owner <em>or</em> a <code>merge</code> label:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">minApprovals:</span></span><br><span class="line"> <span class="attr">OWNER:</span> <span class="number">1</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">requiredLabels:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">merge</span></span><br></pre></td></tr></table></figure><p>This can be combined with conditions on global level, as the global conditions will take precedence. The following example will not trigger a merge when a PR has the <code>blocking</code> label, regardless what the rules say:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">blockingLabels:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">blocking</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">minApprovals:</span></span><br><span class="line"> <span class="attr">OWNER:</span> <span class="number">1</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">requiredLabels:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">merge</span></span><br></pre></td></tr></table></figure><p>Note: remove the whole rules section when you’re not using any rules.</p><h3 id="requiredAuthorRole-default-none"><code>requiredAuthorRole</code> (default: none)<a class="fa-solid fa-hashtag" href="#requiredAuthorRole-default-none"></a></h3><p>Using the <code>requiredAuthorRole</code> condition you can specify conditions based on the role of the pull request author.</p><p>For instance, using <code>rules</code>, one can be more loose when the author is an owner, and more restrictive otherwise.</p><p>Here’s an example of a configuration that requires acceptance of 2 owners or 1 owner if the other owner made the PR:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">requiredAuthorRole:</span> <span class="string">OWNER</span></span><br><span class="line"> <span class="attr">minApprovals:</span></span><br><span class="line"> <span class="attr">OWNER:</span> <span class="number">1</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">minApprovals:</span></span><br><span class="line"> <span class="attr">OWNER:</span> <span class="number">2</span></span><br></pre></td></tr></table></figure><h2 id="Development-2">Development<a class="fa-solid fa-hashtag" href="#Development-2"></a></h2><h3 id="Setup">Setup<a class="fa-solid fa-hashtag" href="#Setup"></a></h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Install dependencies</span></span><br><span class="line">npm install</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Run typescript</span></span><br><span class="line">npm run build</span><br></pre></td></tr></table></figure><h3 id="Testing">Testing<a class="fa-solid fa-hashtag" href="#Testing"></a></h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run test</span><br></pre></td></tr></table></figure><p>or during development:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run test:watch</span><br></pre></td></tr></table></figure><h3 id="Running">Running<a class="fa-solid fa-hashtag" href="#Running"></a></h3><p>See <a href="https://probot.github.io/docs/development/#configuring-a-github-app">https://probot.github.io/docs/development/#configuring-a-github-app</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build && npm run dev</span><br></pre></td></tr></table></figure><h3 id="Running-on-Docker">Running on Docker<a class="fa-solid fa-hashtag" href="#Running-on-Docker"></a></h3><p>This will build and run the app on a container called <code>probot-auto-merge</code>:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run docker</span><br></pre></td></tr></table></figure><p>To just build the container image:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run docker:build</span><br></pre></td></tr></table></figure><p>To run the built image:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run docker:run</span><br></pre></td></tr></table></figure><h3 id="Running-the-linter">Running the linter<a class="fa-solid fa-hashtag" href="#Running-the-linter"></a></h3><p>This will run the linter, pointing out the infractions, but it won’t fix them automatically.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run lint</span><br></pre></td></tr></table></figure><h2 id="Deployment-2">Deployment<a class="fa-solid fa-hashtag" href="#Deployment-2"></a></h2><p>To deploy <code>probot-auto-merge</code> yourself, please follow <a href="https://probot.github.io/docs/deployment/">the guidelines defined by Probot on deploying GitHub applications</a>.</p><p>The permissions and events needed for the app to function can be found below.</p><h3 id="Permissions">Permissions<a class="fa-solid fa-hashtag" href="#Permissions"></a></h3><ul><li>Administration: Read-only</li><li>Checks: Read & write</li><li>Contents: Read & write</li><li>Issues: Read & write</li><li>Metadata: Read-only</li><li>Pull requests: Read & write</li><li>Commit statuses: Read-only</li><li>Members: Read-only</li></ul><h3 id="Events">Events<a class="fa-solid fa-hashtag" href="#Events"></a></h3><ul><li>Check run</li><li>Check suite</li><li>Label</li><li>Pull request</li><li>Pull request review</li><li>Pull request review comment</li><li>Status</li></ul><h2 id="Contributing-2">Contributing<a class="fa-solid fa-hashtag" href="#Contributing-2"></a></h2><p>If you have suggestions for how <code>probot-auto-merge</code> could be improved, or want to report a bug, open an issue! We’d love all and any contributions.</p><p>For more, check out the <a href="CONTRIBUTING.md">Contributing Guide</a>.</p><h2 id="License-3">License<a class="fa-solid fa-hashtag" href="#License-3"></a></h2><p><a href="LICENSE">ISC</a> © 2018 Bob van der Linden <a href="mailto:bobvanderlinden@gmail.com">bobvanderlinden@gmail.com</a> (<a href="https://github.com/bobvanderlinden/probot-auto-merge">https://github.com/bobvanderlinden/probot-auto-merge</a>)</p><h1>auto-label-merge-conflicts</h1><blockquote><p>A Github action to auto-label PRs with merge conflicts</p></blockquote><h2 id="Purpose">Purpose<a class="fa-solid fa-hashtag" href="#Purpose"></a></h2><p>This action checks all open Pull Requests for merge conflicts and marks them with a Github label.</p><p><img src="/./demo.png" alt="" loading="lazy"></p><p>Once a conflict is resolved the label is automatically removed.</p><p>The typical use case is to run this action post merge (e.g. push to <code>master</code>) to quickly see which other PRs are now in conflict.</p><p>We use this setup e.g. on our monorepo at <a href="https://github.com/comtravo">Comtravo</a>. Instead of a grumpy CTO pinging developers to fix their merge conflicts there’s now a shiny bot.</p><h2 id="Set-up">Set up<a class="fa-solid fa-hashtag" href="#Set-up"></a></h2><p>To configure the action on your repo you have to do 2 things:</p><ol><li>pick a Github label that should be used to mark PRs with conflicts</li></ol><p>This label will then be managed by this action. It will be added to PRs with merge conflicts and removed from PRs without conflicts.</p><ol start="2"><li>configure the new workflow by creating a YML config file in your <code>.github/workflows</code> folder:</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">on:</span></span><br><span class="line"> <span class="attr">push:</span></span><br><span class="line"> <span class="attr">branches:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">master</span></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line"> <span class="attr">triage:</span></span><br><span class="line"> <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line"> <span class="attr">steps:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">uses:</span> <span class="string">mschilde/auto-label-merge-conflicts@master</span></span><br><span class="line"> <span class="attr">with:</span></span><br><span class="line"> <span class="attr">CONFLICT_LABEL_NAME:</span> <span class="string">"has conflicts"</span></span><br><span class="line"> <span class="attr">GITHUB_TOKEN:</span> <span class="string">${{</span> <span class="string">secrets.GITHUB_TOKEN</span> <span class="string">}}</span></span><br><span class="line"> <span class="attr">MAX_RETRIES:</span> <span class="number">5</span></span><br><span class="line"> <span class="attr">WAIT_MS:</span> <span class="number">5000</span></span><br></pre></td></tr></table></figure><p>The label from step 1 should be referenced in the parameter <code>CONFLICT_LABEL_NAME</code></p><p>Take a look at <a href="https://github.com/mschilde/auto-label-merge-conflicts/blob/master/%2Egithub/workflows/label_merge_conflicts.yml">this repo</a> for an example setup.</p><h3 id="Arguments">Arguments:<a class="fa-solid fa-hashtag" href="#Arguments"></a></h3><ul><li>MAX_RETRIES: optional (default 5)</li><li>WAIT_MS: optional (default 5000)</li></ul><h2 id="Limitations-2">Limitations<a class="fa-solid fa-hashtag" href="#Limitations-2"></a></h2><p>Github does not reliably compute the <code>mergeable</code> status which is used by this action to detect merge conflicts.</p><p>If <code>master</code> changes the mergeable status is unknown until someone (most likely this action) requests it. <a href="https://stackoverflow.com/a/30620973">Github then tries to compute the status with an async job.</a></p><p>This is usually quick and simple, but there are no guarantees and Github might have issues.</p><p>You can tweak <code>MAX_RETRIES</code> and <code>WAIT_MS</code> to increase the timeout before giving up on a Pull Request.</p><h2 id="Local-dev-setup">Local dev setup<a class="fa-solid fa-hashtag" href="#Local-dev-setup"></a></h2><p>To play around with the code base, you need <code>Docker</code> and <code>make</code> set up locally.</p><p>Run <code>make build</code>, <code>make develop</code>, then <code>yarn install</code>.</p><h1>How to use PR Valet</h1><p>Step 1: Install <a href="https://github.com/marketplace/pr-valet">PR Valet</a>.</p><p>Step 2: Add the <code>valet:merge</code> label to your pull request.</p><p>Step 3: Work on your other tasks while PR Valet takes care of merging your pull request.</p><h1><a href="https://docs.mergify.io/">https://docs.mergify.io/</a></h1><h1><a href="https://snyk.io/">https://snyk.io/</a></h1>]]></c:encoded></item></channel></rss>