對許多人來說,依賴關系是一場噩夢。一些人甚至認為它們是技術債務。管理你的軟件的庫列表是一種可怕的體驗。自動更新依賴項?-這聽起來像是在說胡話。
請繼續關注我,因為我將幫助你更好地掌握一些你在實踐中無法擺脫的東西——除非你非常富有和有才華,能夠在沒有他人代碼的情況下生活。
首先,我們需要清楚地了解一些有關依賴關系的知識: 依賴關系有兩種類型。Donald Stuff幾年前寫的關于這個主題的文章比我要寫的都好。簡單一點來說,它們是依賴于外部代碼的兩種類型的代碼包:應用程序和庫。
庫依賴
Python庫應該以一種通用的方式來指定它們的依賴關系。一個庫不應該要求requests 2.1.5:這沒有意義。如果每個庫都需要不同版本的requests,我們就不能同時使用它們。
庫需要根據版本號的范圍來聲明依賴關系。要求請求requests>=2是正確的。如果你知道requests2.x不適用于該庫,那么要求 requests>=1,<2 也是正確的。你的版本范圍定義正在解決的問題是你的代碼和依賴項之間的API兼容性問題———沒有其他問題。這是庫盡可能使用語義版本控制的一個很好的理由。
因此,依賴關系應該寫在setup.py中,類似于:
這樣,任何應用程序都可以輕松地使用庫并與其他應用程序共存。
應用程序依賴關系
應用程序只是庫的一種特殊情況。它們不打算被其他應用程序庫重用(導入)——盡管在實踐中沒有什么可以阻止它。
最后,這意味著你應該像為一個庫指定依賴關系一樣來在應用程序的setup.py中指定依賴關系。
其主要區別在于,一個應用程序通常部署在生產環境中以提供其服務。部署需要是可復用的。為此,你不能僅僅依賴于setup.py:因為請求的依賴關系范圍太寬。在重新部署應用程序時,你希望隨時都可以隨意更改版本。
因此,你需要一個不同的版本管理機制來處理部署,而不僅僅是setup.py。
pipenv在其文檔中有一節很好地總結了這一點。它將依賴關系類型劃分為抽象依賴項和具體依賴項: 抽象依賴項基于范圍(例如 庫),而具體依賴項是用精確的版本(例如應用程序部署)指定的——正如我們在這里看到的。
處理部署
requirements.txt文件長期以來一直被用來解決應用程序部署的可復用性問題。它的格式通常是這樣的:
每個庫都將自己指定為微版本。這確保你的每個部署都將安裝相同版本的依賴項。使用requirements.txt是一個簡單的解決方案,也是實現可復用部署的第一步。然而,這還不夠。
實際上,雖然你可以指定你想要的requests的版本,但是如果requests依賴于urllib3,那么這將會使pip安裝urllib 2.1或urllib 2.2。你無法知道哪一個會被安裝,這并不能使你的部署100%可重用。
當然,你可以在你的requirements.txt中復制所有的requests依賴項,但那將是瘋狂的做法!
一個應用程序依賴關系樹有時可能非常深入和復雜。
有各種各樣的技巧可以用來修復這個限制,但是真正的救星是pipenv和poetry。它們解決這個問題的方法類似于其他編程語言中的許多包管理器。它們生成一個鎖文件,其中包含所有已安裝的依賴項(以及它們自己的依賴項等)的列表和版本號。這可以確保部署是100%可復用的。
請查看它們的文檔,了解如何設置和使用它們!
處理依賴項更新
現在,你已經有了鎖文件,它可以確保你的部署在短時間內是可復用的,那么你就有了另一個問題。你如何確保你的依賴項是最新的?這是一個真正的安全問題,而且保持版本落后的話,你可能也會錯過bug修復和進行優化的機會。
如果你的項目托管在GitHub上,Dependabot是解決這個問題的一個很好的解決方案。當你的鎖文件中列出的庫的一個新版本可用時,在存儲庫上啟用此應用程序將會自動創合并請求。例如,如果你已經使用redis 3.3.6部署了你的應用程序,當新版本redis 3.3.7發布時,Dependabot將會創建一個更新到redis 3.3.7的合并請求。此外,Dependabot還支持requirements.txt、 pipenv和poetry!
Dependabot正在為你更新jinja2
自動部署更新
快要成功了。你有一個機器人,它讓你知道你的項目需要的一個庫的新版本是可用的。
一旦創建了合并請求,你的持續集成系統就會啟動、部署你的項目并運行測試。如果一切正常,你的合并請求就可以被合并了。但是在這個過程中真的需要你參與嗎?
除非你個人特別反感某個特定的版本號——“天哪,我討厭以3結尾的版本。遇見它總是運氣不好。——或者除非你沒有自動化測試,否則你,人類,是無用的。這個合并完全可以是自動化的。
這就是Mergify發揮作用的地方。Mergify是一個GitHub應用程序,它允許你定義關于如何合并合并請求的精確規則。下面是我在每個項目中都使用的一個規則:
當規則完全匹配時,Mergify會進行報告。
一旦你的持續集成系統通過,Mergify就會為你合并該合并請求。
然后,你就可以自動觸發你的部署鉤子來更新你的生產部署,并立即安裝新的庫版本。這將使得你的應用程序總是使用較新的庫進行更新,并且不會落后于幾年的發行版。
如果出現任何錯誤,你仍然能夠從Dependabot中恢復提交——如果你希望使用一個Mergify規則,你也可以自動化恢復提交。
題外話
對我來說,這就是依賴關系管理生命周期目前的狀態。雖然這對Python非常適用,但它也可以應用于使用了類似模式的許多其他語言,比如Node和npm。
英文原文:https://julien.danjou.info/dependencies-handling-in-python-automatic-update/
譯者:天天向上