展開所有 GitHub comment 的 Bookmarklet

看到 Eric Meyer 弄了一個可以展開 GitHub comment 的 bookmarklet:「Bookmarklet: Load All GitHub Comments」。

分析他的程式碼,稍微手動排一下,可以看出來邏輯蠻簡單的,就是去找出對應的 button,然後模擬按下去的 event:

javascript:function start() {
  let buttons = document.querySelectorAll('button');
  let loaders = [];
  for (let i = 0; i < buttons.length; i += 1) {
    if (buttons[i].textContent.trim() == 'Load more%E2%80%A6') {
      loaders.push(buttons[i]);
      buttons[i].dispatchEvent(new MouseEvent('click', {
        view: window,
        bubbles: false
      }))
    }
  }
  if (loaders.length > 0) {
    setTimeout(start, 5000)
  }
}
setTimeout(start, 500);
void(20240130);

意外可以看到一些應該是作者以前寫習慣的寫法 (畢竟 Eric Meyer 這個名字二十年前就聽過了?),現在 for 拿來當 iteration 應該會用 of 的語法了,另外是 letconst 的差異...

還好這邊還是用 querySelectorAll(),而不是直接看到 getElementsByTagName(),不然就更有考古感了...

拿「Quadratic time internal base conversions #90716」這個測了一下還行,不過我不是那麼常用到,大概不會掛到 bookmark bar 上面...

作者有提到考慮過寫成 userscript,不過看起來是懶 XD

GitHub 新版 Code Search 後面砍掉重練的過程

Hacker News 上看到「Lessons from building GitHub code search (youtube.com)」這篇在講 GitHub 的 Code Search (今年九月在 Strange Loop 上的演講),同時演講者 Luke Francl (帳號是 100k) 也有在 Hacker News 上留言回答一些問題:

影片裡面有不少資訊,挑我自己覺得有趣的地方整理一下。(不是依照影片的順序)

首先是現成的 search engine (Elasticsearch) 會濾掉太多資訊,其中一種例子就是在程式語言中,各種 token 像是 <= 以及 > 這些,都算是有用的資訊。

另外一方面是 Elasticsearch 的架構下沒有辦法利用 fork 的性質 (以及 Git 的 branch 性質),所以在處理 fork 類的 repository 會造成大量重複的資料,但 fork 的資料會有 99% 以上是與原來的 repository 相同。

舊的系統有 312 servers,包括了 24960 cores 與 20TB RAM,直接平均下來,每一台機器是 80 cores 與 65GB RAM,而跑一次 reindex 會需要幾個月的時間。

新的系統則降到了 130 servers,包括了 8320 cores,但記憶體加到了 65TB RAM,直接平均下來,每一台機器是 64 cores 與 512GB RAM,後面有列出來是 Azure 的 L64s v3,剛好就是 64 cores 與 512GB RAM,然後帶有 640GB temp disk 與 8*1.92TB 的 NVMe disk。

另外有提到這套新的系統雖然比較小 (除了記憶體),但卻是 3 clusters,這也剛好解釋記憶體變成原來三倍的原因。

而更重要的是,因為有多個系統,所以他們可以在上面對 production 等級資料量進行測試,而且不用害怕炸掉東西。

而且新的系統從零 rebuild 一次只需要幾天,不像之前需要好幾個月。這些改變使得 engineer 更容易進行個重嘗試與改善,而不用把精神花在要怎麼維持相容性。

回到 CPU 數量的下降,這邊沒有直接提到原因,但演講裡有提到有不少東西改用 Rust 寫,等於是從 JVM 換到原生程式碼,對於會有大量時間花在 CPU 運算的服務來說是個明顯的加分。

中間有兩個提到演算法的事情也蠻有趣的。

第一個是在 Delta compression 的地方,把 fork 後的差異當作是 delta,要最小化整個 fork tree 的成本,剛好把這個東西轉換成圖論的問題,就可以套用 Minimum spanning tree 這個經典的演算法,而且 MST 太經典,有很多變形也都有人研究過,有限成的演算法可以用。

另外一個提到的是 Alexander Neubeck,從 LinkedIn 上的資料可以看到他在 Google 的時候就是負責 Code Search,後來到 GitHub 看起來剛好加入對應的團隊,他開發了一個新的資料結構 Geometrics XOR filter 來解決 Delta compression 遇到的問題。

在 Hacekr News 上的討論可以看到有人抱怨還是缺了重要的功能,不過這畢竟是砍掉重練開始搞,而且是配合 Git 與 GitHub 的特性設計的,可以預期會缺東西,但就像演講裡提到的,新的架構可以讓整個團隊更快的迭代進行各種嘗試,後續就比較會是官方要取捨實作哪些功能了...

GitHub 的 MySQL 5.7 升級到 8.0 的細節

GitHub Blog 上面寫了一篇關於 GitHub 怎麼把 MySQL 5.7 升級到 8.0 的過程,有點長度但是裡面有蠻多數字與架構可以看:「Upgrading GitHub.com to MySQL 8.0」。

開頭先順便提一下,看這篇後可以交叉看 GitHub 的 Incident History,有幾次跟 database 有關的事件,雖然不能直接確認與這波升級有關,但心裡可以有個底...

數字與時間的部分主要是這些:

Our fleet consists of 1200+ hosts. It’s a combination of Azure Virtual Machines and bare metal hosts in our data center.

We store 300+ TB of data and serve 5.5 million queries per second across 50+ database clusters.

Preparation for the upgrade started in July 2022 and we had several milestones to reach even before upgrading a single production database.

另外雖然沒有明講,但從文章中其他段落的描述,以及相關的圖片,可以看出來 GitHub 是使用 single-primary (single-master) 的架構,這邊沒有用到 multi-primary (multi-master) 類的架構:

We opted not to do direct upgrades on the primary database host. Instead, we would promote a MySQL 8.0 replica to primary through a graceful failover performed with Orchestrator.

後續升級的部分有點長,第一波關於 read-only replica 的部分雖然有些地方沒講清楚,但基本上大家的作法都大同小異:

比較明顯有疑問的是,第一步為什麼不是直接生一台新的 8.0 觀察 (這樣觀察到的環境才會與後續過程接近),而是 in-place upgrade,而後續開的機器又是 provision。不過這個算是小問題...

比較值得研究的是在第二步與第三步的說明裡面提到的 primary (master) 這塊。

第二步是先改變 topology,這個架構算是蠻特別的的過渡架構,只會維持幾個小時;會把其中一台 8.0 replica 拉起來放在中間,然後再串一台 5.7 replica,接下去再串 5.7/8.0 的 read-only replicas:

第三步把 primary (master) 指到 8.0 上:

這個特別的架構可以推敲出來是想要能夠快速在有狀況時完全 rollback 回 5.7,不過可以馬上想到 8.0 的資料丟到 5.7 上的問題。

MySQL 的慣例是下一個版本的 replication 通常都會通 (像是 5.0 -> 5.1,或是 5.1 -> 5.5,而這邊的例子是 5.7 -> 8.0),這在官方的文件「Replication Compatibility Between MySQL Versions」有提過。

但反過來就不一定了,這也是看到圖時馬上會想到的問題,在文章裡面也有提到:

MySQL supports replication from one release to the next higher release but does not explicitly support the reverse (MySQL Replication compatibility).

所以他們只能在 staging 上演練看看,找出會炸掉的東西,然後得提前先修改完:

When we tested promoting an 8.0 host to primary on our staging cluster, we saw replication break on all 5.7 replicas.

另外一方面,在文章開頭的地方也有提到利用 CI 事先找出問題:

We added MySQL 8.0 to Continuous Integration (CI) for all applications using MySQL. We ran MySQL 5.7 and 8.0 side-by-side in CI to ensure that there wouldn’t be regressions during the prolonged upgrade process. We detected a variety of bugs and incompatibilities in CI, helping us remove any unsupported configurations or features and escape any new reserved keywords.

用這些方法儘量把問題圍堵找出來,而真的遇到在 production 上的問題時,應該是看情況來決定要不要 rollback 回 5.7 整包重來?

就... 看看當作一個有趣的 case study。

測試 GitHub 與 AWS 可以多快偵測出外洩的 token

前幾天在 Hacker News 上看到「What happens when you leak AWS credentials and how AWS minimizes the damage (xebia.com)」這篇,原文連結在「What happens when you leak AWS credentials and how AWS minimizes the damage」這邊。原文跟 Hacker News 上的寫到東西都頗有趣的,可以分開來講。

先是原文的部份,他抓了一些時間軸:

12:33:12 – Pushed the credentials to GitHub
12:34:19 – The AWSCompromisedKeyQuarantineV2 policy is attached to the IAM user test-user by AWS
12:34:32 – Various List and Describe calls are made using the leaked credentials
12:35:08 – Received an email from AWS with the subject ‘ACTION REQUIRED: Your AWS Access Key is Exposed for AWS Account 12345678’

可以看到推上 GitHub 後,AWS 在一分七秒後就自動加上 AWSCompromisedKeyQuarantineV2 以減少災害擴大,然後再發信件通知。

這個功能可以參考 GitHub 的文件說明:「About secret scanning - GitHub Docs」。

另外在 Hacker News 上面看到有人直接把 secret scanning 當作 API 串來用 (噗),把在 PyPI 上面掃到的 AWS secret 丟上 GitHub 觸發後續的機制:

I set up a project[1] to automatically leak AWS secrets published to the Python package index, which then triggers the secret scanning process and quarantines the keys[2]

1. https://github.com/pypi-data/pypi-aws-secrets

2. https://github.com/pypi-data/pypi-aws-secrets/blob/main/keys...

Gitea 推出 Actions

Hacker News 上看到 Gitea 出 1.19 的消息:「Gitea 1.19 (gitea.io)」,在討論裡面就有人提到 Gitea Actions,從名字就知道是抄自 GitHub Actions,算是 Gitea 開始建立自己的 DevOps 生態系的一個重要功能。

目前這個功能還被掛在 EXPERIMENTAL 上,預設是關閉的,而且我自己試了一下也的確試跑不太起來,出現這樣的錯誤訊息,暫時也沒空去細追:

time="2023-03-28T17:36:37Z" level=info msg="poller: request stage from remote server" func=pollTask
time="2023-03-28T17:36:37Z" level=error msg="cannot accept task" error="unknown: rpc error: code = Internal desc = pick task: CreateTaskForRunner: Error 1366 (HY000): Incorrect string value: '\\xF0\\x9F\\x8E\\x89 T...' for column 'name' at row 1" func=pollTask
time="2023-03-28T17:36:37Z" level=error msg="can't find the task: unknown: rpc error: code = Internal desc = pick task: CreateTaskForRunner: Error 1366 (HY000): Incorrect string value: '\\xF0\\x9F\\x8E\\x89 T...' for column 'name' at row 1" func=Poll

接下來會有更多人跳進去試,之後再來看看成熟度如何...

GitHub 更換 github.com 的 SSH host key (RSA 部份)

看到 GitHub 宣佈更換 SSH key (RSA 的部份):「We updated our RSA SSH host key」。

Hacker News 上的「We updated our RSA SSH host key (github.blog)」這邊有人提到官方文件 (原文裡面也有提到),裡面會列出對應的 key:「GitHub's SSH key fingerprints」。

只是看起來這些大公司依然對 DNSSEC + SSHFP 這樣的組合沒興趣...

Fake GitHub Star 的生意

昨天在 Hacker News 首頁上看到「Tracking the Fake GitHub Star Black Market (dagster.io)」這篇,原文在「Tracking the Fake GitHub Star Black Market with Dagster, dbt and BigQuery」這邊。

作者群想要偵測 GitHub 上面 fake star 的行為,所以就跑去找黑市買,然後找到了兩家,Baddhi Shop (1000 個 $64) 與 GitHub24 (每個 €0.85,大約是 $0.91),價錢差異很大,「品質」差異也很大:貴的 star 在一個月後還是存在,而便宜的看起來有一些有被 GitHub 偵測到而清除掉:

A month later, all 100 GitHub24 stars still stood, but only three-quarters of the fake Baddhi Shop stars remained. We suspect the rest were purged by GitHub’s integrity teams.

接下來就是想要系統化分析,切入點是 GH Archive 這個服務,可以直接下載 GitHub 全站上的 public evnets 資料:

GH Archive is a project to record the public GitHub timeline, archive it, and make it easily accessible for further analysis.

想要偵測兩種不同的 fake account,第一種是 obvious fake account,定義成這樣:

  • Created in 2022 or later
  • Followers <=1
  • Following <= 1
  • Public gists == 0
  • Public repos <=4
  • Email, hireable, bio, blog, and twitter username are empty
  • Star date == account creation date == account updated date

從定義就可以看出來完全就是灌水帳號,開出來就沒在動的。從 screenshot 可以看出這種帳號長的都一樣:

另外一種則是透過演算法去分析,這邊拿 unsupervised clustering 類的演算法分析出來的結果,可以看到抓到很多:

最近 NN 類的 machine learning 演算法太多,看到這些傳統的 machine learning 演算法還是覺得頗新鮮的...

GitHub 自己開發的搜尋引擎

前陣子 GitHub 發了一篇文章,說明自己開發搜尋引擎的心路歷程:「The technology behind GitHub’s new code search」。

看了一下其實就是自己幹了一套 search engine cluster,然後針對 code search 把一些功能放進去。

目前這套 search enginer 還是 beta 版本,全站兩億個 repository 只包括了 4500 萬 (大概 22% 左右),然後已經有 115TB 的程式碼了;另外也題到了先前導入 Elasticsearch 時的數字是 800 萬個 repository:

GitHub’s scale is truly a unique challenge. When we first deployed Elasticsearch, it took months to index all of the code on GitHub (about 8 million repositories at the time). Today, that number is north of 200 million, and that code isn’t static: it’s constantly changing and that’s quite challenging for search engines to handle. For the beta, you can currently search almost 45 million repositories, representing 115 TB of code and 15.5 billion documents.

目前是 32 台機器,沒有特別提到記憶體大小,也沒有提到 replication 之類的數字:

Code search runs on 64 core, 32 machine clusters.

然後各種 inverted index 與各種資料在壓縮後只有 25TB:

There are some big wins on the size of the index as well. Remember that we started with 115 TB of content that we want to search. Content deduplication and delta indexing brings that down to around 28 TB of unique content. And the index itself clocks in at just 25 TB, which includes not only all the indices (including the ngrams), but also a compressed copy of all unique content. This means our total index size including the content is roughly a quarter the size of the original data!

換算一下,就會發現現在已經是「暴力」可以解很多事情的年代了,而這已經是全世界最大的 code hosting。

以前隨便一個主題搞大一點就會撞到 Amdahl's law,現在輕鬆不少...

GitHub 宣佈將在 2024 移除對 Subversion 支援

GitHub 從 2010 年的愚人節時宣佈支援 Subversion:「Announcing SVN Support」,雖然是愚人節的功能,但這個功能是會動的。

而這個功能出現十多年後,可以預期用的人愈來愈少。前幾天 GitHub 宣佈將在大約一年後的 2024/01/08 停止支援 Subversion:「Sunsetting Subversion support」。

然後在 Hacker News 上的討論「GitHub Sunsetting Subversion Support (github.blog)」則是直接讓 Scott Chacon (GitHub co-founder,同時也是第一篇公告文的作者 + 這個功能的兇手之一) 出來解釋當初搞出這個東西的前因與後果,還有一些感想。

裡面有提到這個功能當初推出來的時候是個好玩的性質,但意外的在上線後發現也讓一些老系統可以比較容易轉移:也就是讓 developer 可以先開始用 Git,但 CI 類的工具可以先不用改。

As one of the GitHub cofounders and the brainchild of this particular feature, I want to let everyone know that this is maybe the funniest thing I've ever done.

We released this feature and published the announcing blog post, on April Fool's Day, 2010. I remember demoing it to the other GitHub guys and saying how funny it would be if we made this an April Fool's day post as though it was a big stupid joke but then it actually completely worked on every repository we had and we all thought it would be great. Until nobody believed us. Which in hindsight we should have seen coming, since that was the joke, but nobody actually tried it. Then people tried it and it worked and they thought it was a trick or something.

It was really helpful for people migrating from legacy SVN based systems to us (CI and stuff) but I'm surprised to some degree that it's still running 13 years later when nobody is really facing that issue anymore. And I'm still undecided if the joke was worth the massive confusion it caused. But if I'm pressed, I would say that I would 100% release it on April Fool's Day again.

不過想要拔掉這個功能的起因不知道是什麼,技術債不知道有多少...

GitHub 的 2FA 新計畫

GitHub 決定擴大強制使用 2FA 的範圍:「Raising the bar for software security: next steps for GitHub.com 2FA」。

本來的 2FA policy 是在「Software security starts with the developer: Securing developer accounts with 2FA」這邊提到的,所有的使用者預定在 2023 年年底強制使用 2FA:

GitHub will require all users who contribute code on GitHub.com to enable one or more forms of two-factor authentication (2FA) by the end of 2023.

另外針對 npm 熱門套件的維護者,則是在三月 (top 100) 與五月 (top 500) 就強制要使用了:

In February we enrolled all maintainers of the top-100 packages on the npm registry in mandatory 2FA, and in March we enrolled all npm accounts in enhanced login verification. On May 31, we will be enrolling all maintainers of the top-500 packages in mandatory 2FA.

但到 2023 年年底才有動作會有點久,所以這次宣佈在 2023 年三月會插入一個新階段,強制這些人要有 2FA 才能進行變更類的操作:

  • Users who published GitHub or OAuth apps or packages
  • Users who created a release
  • Users who are Enterprise and Organization administrators
  • Users who contributed code to repositories deemed critical by npm, OpenSSF, PyPI, or RubyGems
  • Users who contributed code to the approximate top four million public and private repositories

以 developer 為主的 GitHub 大力在推 2FA,其他的服務不知道之後會不會有類似動作...