構(gòu)建一個 Ruby Gem 第五章 發(fā)布

發(fā)布

在第二章中, 我們簡要的看了一下默認(rèn)的 bundler 給我們創(chuàng)建的 Rakefile:

require "bundler/gem_tasks"

這單獨(dú)的一行可以讓我們輕松的發(fā)布我們的 gem。如果我們在命令行輸入 rake -T,我們會看到下面的內(nèi)容:

$ rake -T
rake build   # Build mega_lotto-0.0.1.gem into the pkg directory
rake install  # Build and install mega_lotto-0.0.1.gem into system gems
rake release  # Create tag v0.0.1 and build and push mega_lotto-0.0.1.gem
                       # to Rubygems

rake build 將會創(chuàng)建一個帶版本號的 .gem 文件在我們的 gem 的 pkg/ 目錄下,bundler 創(chuàng)建了一個 .gitignore 文件來把 pkg/ 目錄排除到 git 版本控制之外。所以即使在運(yùn)行 rake build 命令后,被打包的 *.gem 文件也不會被提交到源碼庫。

rake install,顧名思義,將會把 gem 安裝到本地。不過既然我們可以在一個 Gemfile 中指定本地路徑的gem (通過 path 選項),我沒發(fā)現(xiàn)這個任務(wù)有什么有用的地方。

rake release 是黃金門票... 正如我們從命令的描述中看到的一樣,它檢查我們的 gem 的當(dāng)前版本并且建議它要發(fā)布v0.0.1 版本,基于 lib/mega_lotto/version.rb 文件。

module MegaLotto
  VERSION = "0.0.1"
end

執(zhí)行 rake release 命令將會做如下的事情:

  1. 構(gòu)建我們的gem包并且把它放在 pkg/ 目錄下
  2. 為當(dāng)前版本(0.01)創(chuàng)建一個 git tag 并且把我們的改變推送到Github上
  3. 把我們打包好的gem推送到 Rubygems,讓它能被公開訪問

注意: 如果你不想開源你的 gem,rake release 目前不適合你。

源代碼管理

雖然 git 不是唯一的源代碼管理選擇,它是 bundler 的內(nèi)建工具并且可以輕松的和Github同步。如果你沒有選擇其他工具的理由,git 和 Github 將會是我的源代碼管理和遠(yuǎn)程倉庫的選擇。

rake release task 假定我們已經(jīng)設(shè)置好了本地的git倉庫并且和Github的遠(yuǎn)程倉庫同步,所以讓我們這樣做把。

我們可以在 gem 的根目錄運(yùn)行 git init。一旦初始化后,我們將會通過 git add。 并且創(chuàng)建一個提交叫做 “Initial commit” 來暫存我們迄今為止的工作。

為了能遠(yuǎn)程同步,我們將會在 Github 上創(chuàng)建一個新的倉庫。我們把它命名為 mega_lotto 并且配置它為公開倉庫因為我們的目的是開源這個項目。
雖然倉庫的名字不一定非要和gem的名字相符,但是取不同的名字會使人迷惑。對于剩下的選項,我們保持默認(rèn)值。

現(xiàn)在遠(yuǎn)程倉庫被創(chuàng)建好了,我們將要在我們的本地倉庫加上引用。下面的命令就是為我們做這件事的:

$ git remote add origin git@github.com:brandonhilkert/mega_lotto.git

注意:遠(yuǎn)程 git 倉庫的路徑將會包含你的 Github 用戶名和你的倉庫的名字。要替換掉相應(yīng)的內(nèi)容。

現(xiàn)在我們的遠(yuǎn)程倉庫已經(jīng)被正確的配置了,我們將會推送我們的本地倉庫的內(nèi)容到 Github 使用命令:

$ git push -u origin master

今后,任何時候我們想要同步到 Github,使用縮寫 git push 命令就可以了!

發(fā)布

讓我們再次運(yùn)行我們測試套件來確保事情都很順利:

$ rake 
....

Finished in 0.00401 seconds
4 examples, 0 failures

Randomized with seed 63009

測試通過,感覺良好。

注意:如果我們想要我們的 gem 被上傳到 rubygems.org,我們首先要創(chuàng)建一個賬號。

運(yùn)行 rake release 命令:

$ rake release
mega_lotto 0.0.1 built to pkg/mega_lotto-0.0.1.gem.
Tagged v0.0.1.
Pushed git commits and tags.
Pushed mega_lotto 0.0.1 to rubygems.org.

注意:Rubygems 不允許提交重復(fù)名字的 gems。因為我之前已經(jīng)發(fā)布了名叫 MegaLotto 的gem,如果你照著上面的做法做的話會返回的一個rubygems的錯誤。

注意: Rubygems 要求身份驗證,所以你在發(fā)布之前會被要求輸入你的email和密碼。

rake release 的結(jié)果會產(chǎn)生在這個頁面上。正如你所看到的,它解析了mega_lotto.gemspec 的內(nèi)容并且加上了我的名字,照片,gem 的版本,發(fā)布的日期和 gem 的依賴。它也推送到github gem 的 release tag。

下一次發(fā)布

假設(shè)我們想要讓 mega_lotto gem 返回6個 integers 而不是 5個。為了實現(xiàn)它,我們改變了 specs:

it "returns an array with 5 elements" do 
  expect(draw.size).to eq(5)
end

改為:

it "returns an array with 6 elements" do 
  expect(draw.size).to eq(6)
end

正如預(yù)期的,我們的測試套件現(xiàn)在失敗了因為我們還沒有升級我們的實現(xiàn):

$ rake
..F.
Failures:
  1) MegaLotto::Drawing#draw returns an array with 6 elements 
      Failure/Error: expect(draw.size).to eq(6)

         expected: 6          
              got: 5

        (compared using ==)
      # ./spec/mega_lotto/drawing_spec.rb:13

Finished in 0.00325 seconds
4 examples, 1 failure

Failed examples:

rspec ./spec/mega_lotto/drawing_spec.rb:12
# MegaLotto::Drawing#draw returns an array with 6 elements
Randomized with seed 8922

現(xiàn)在讓我們改變我們的實現(xiàn):

module MegaLotto 
  class Drawing
    def draw
      # This value used to be 5 
      6.times.map { single_draw }
    end
    private
    def single_draw 
      rand(0...60)
    end 
  end
end

并且運(yùn)行測試再次確認(rèn):

$ rake 
....

Finished in 0.00482 seconds
4 examples, 0 failures

Randomized with seed 14164

很好!讓我們繼續(xù)前進(jìn)...
通常來說,我們將會創(chuàng)建一個緊隨其后的提交來 bumping lib/mega_lotto/version.rb 文件里的版本號常量:

module MegaLotto 
  VERSION = "0.0.2"
end

注意:我們在下一章會討論的,推薦遵從語義化的版本控制。通過改變 mega_lotto gem 返回 6 個數(shù)字而不是 5 個,我們改變了實現(xiàn)。如果我們拘泥于遵從語義化版本控制,我們應(yīng)該發(fā)布一個主版本號而不是一個補(bǔ)丁。做實驗并沒有什么錯只要你讓用戶知曉。最好的方式就是說明這個 gem 正在開發(fā)中。

開發(fā) public API 多半就是不斷改變版本。通常來說,這適用于版本小于 1.0 的情況,這和項目相應(yīng)變化?,F(xiàn)在我們的新版本已經(jīng)準(zhǔn)備好要發(fā)布了,讓我們再次快速看看 rake 命令的說明:

$ rake -T
rake build   # Build mega_lotto-0.0.2.gem into the pkg directory
rake install  # Build and install mega_lotto-0.0.2.gem into system gems
rake release  # Create tag v0.0.2 and build and push mega_lotto-0.0.2.gem
                        # to Rubygems

正如我們看到的,rake 命令知道我們將要發(fā)布 0.0.2 版本 (因為我們 bumped了 lib/mega_lotto/version 的VERSION 常量)。所以我們還在等什么呢???發(fā)布吧!

$ rake release
mega_lotto 0.0.2 built to pkg/mega_lotto-0.0.2.gem.
Tagged v0.0.2.
Pushed git commits and tags.
Pushed mega_lotto 0.0.2 to rubygems.org.

我們的新版本會在 Rubygems landing pagethe Github releases page 被顯示出來。

何時發(fā)布

很不幸,沒有關(guān)于何時發(fā)布方面的規(guī)則。然而,你大概注意到了,在大型軟件項目中 (Google Chrome, Mozilla Firefox 等等),更小更頻繁的發(fā)布是主流方式。語義化版本號已經(jīng)創(chuàng)建了一個可信賴的模式來發(fā)布可預(yù)測的軟件。

我非常確定我同意 "有 bug 就發(fā)布一個 fix" 的說法 (但是我們都寫沒 bug 的代碼,不是嗎?!?!)

除此以外,你將不得不平衡多少特性或者改變你一次想要發(fā)布。并且這會,幾乎一定,在項目的生命周期中不斷變化。在開發(fā)初期,預(yù)期會有大量的改變是合理的。雖然有一些不太可靠。然而,隨著項目的成熟和越來越多的人依賴它,我的建議是更頻繁的發(fā)布小的改變。

總結(jié)

從啟動項目到提供發(fā)布任務(wù),在我們的 gem 開發(fā)過程中 bundler 是一個必不可少的工具。不必?fù)?dān)心元數(shù)據(jù)或在 git 中應(yīng)用正確的版本號, bundler 出現(xiàn)在需要它的地方。

在下一章,我們會近距離看看語義化版本號并學(xué)習(xí)一個可預(yù)測版本系統(tǒng)所帶來的好處。我們也會看到版本在管理 gem 依賴中扮演的角色。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容