」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 發布 CLI 應用程式(使用 Apt 和 YUM)

發布 CLI 應用程式(使用 Apt 和 YUM)

發佈於2024-11-08
瀏覽:294

Publishing CLI Apps (with Apt & YUM)

简介

我最近非常喜欢 CLI 应用程序。也许这是我童年时期终端的诱惑(从 486/33 上的 DOS 和我父亲的旧 Apple IIe 开始)。对于 X 代 Commodore64 时代,我出生得有点晚,但正好赶上了了解 Windows 95 之外的更多内容。那是一个有趣的时代,当时拨号和 56k 调制解调器还是王者。我知道现在大多数博客文章都有一些介绍性的内容,以增加 SEO 的字数,但这确实是为什么我仍然喜欢 CLI,因为现在很多年轻人只知道 GUI 应用程序。看到 Z 世代的孩子们打开终端,即使是为了简单的任务,没有什么比这更让我高兴的了。伙计,等阿尔法一代知道什么是 BBS 吧。他们可能会说“电脑爷爷”? “离开我的草坪”✊✊

像 CoolRetroTerm 这样的项目在我心里肯定有一个温暖的地方,因为它带回了对 CLI 的热爱。我仍然更喜欢在我的旧上网本上用 Micro 写一些博客,真的让你专注于写作。我猜 VSCode ZenMode 和 MarkText 很接近?


flowchart LR
Build_App --> GH_Actions --> ??? --> Profit!!!



包装

不管怎样,我离题了……

所以在编写我的小 CLI 应用程序 Stampy 后,我遇到了一个小问题,如何分发它?我至少足够聪明,能够思考并用 GoLang 编写它(就像我想用 Python 构建它一样)以避免 Python 包装的可怕愤怒。一直困扰我的一件事是,人们如何将他们漂亮的 CLI 应用程序发布到 APT 和 YUM 等精美的包管理系统。

通常要构建您的应用程序,您只需执行简单的 go build 即可。和繁荣,即时二进制。尽管这对于本地开发来说非常有用,但对于跨平台编译却没有多大好处。有一些很好的指南可以向您展示如何做到这一点,但是... tl;dr 我的??。所以我做了更多的挖掘,必须有一个不错的工具......当然,有 GoReleaser!

阅读了一些写得很好的文档后,我能够快速进行本地跨平台构建,非常简单。


goreleaser --snapshot --clean



通过 GitHub 版本进行构建也很容易,因为它们有很好的预先编写的 GH 操作!

用户现在可以使用 eget(好)和 Steute(更好)等工具安装我的应用程序!

虽然您也可以安装 github.com/xxx,但要做的就是克隆存储库,在本地构建它,然后将 bin 放入您的 $GOBIN 文件夹中。与正确的包管理工具并不完全相同,但对于已经安装了 Go 的人来说确实有用。恕我直言,对于普通用户来说这并不是一个真正的选择。 ?

不仅如此,GoReleaser 还提供包装!现在您可以轻松制作 DEB 和 RPM。我离害怕的 apt-get install stampy 又近了一步。唯一缺少的是如何创建 APT 存储库。这最后一个关键部分肯定并不容易。我花了一个小时左右的时间研究如何使用 GitHub Pages 自行托管它,虽然这是可行的,但使用像 Packagecloud 这样的免费服务来处理签名和存储库托管要容易得多,而且成本低廉,每次 0 美元月?。

您可以在此处查看整个工作流程的示例

我还将在代码块中包含它的精简版本,供任何偶然发现博客文章本身的人使用。

为了获得高层次的概述,GHA 执行以下操作:

  • 写出 GoReleaser 配置
  • 运行发布程序本身
  • 上传下一个作业的 .debs
  • 在链式作业中,我们提取 .deb 并将其上传到 PackageCloud
  • 完毕!

GitHub 操作示例


name: Release

on:
  pull_request:
  push:
    # run only against tags
    tags:
      - "*"

permissions:
  contents: write
  packages: write
  issues: write

jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: stable

      - name: Release config
        run: |
          cat  /tmp/goreleaser-github.yaml
          project_name: EXAMPLE
          version: 2
          builds:
            - env: [CGO_ENABLED=0]
              goos:
                - linux
              goarch:
                - amd64
          nfpms:
            -
              maintainer: YOU 
              bindir: /usr/local/bin
              description: Copy formatted timestamp to system clipboard
              homepage: https://github.com/USERNAME/REPO
              license: MIT
              formats:
                - deb

          release:
            draft: false # If set to true, will not auto-publish the release.
            replace_existing_draft: true
            replace_existing_artifacts: true
            target_commitish: "{{ .Commit }}"
            prerelease: auto
            make_latest: true
            mode: replace
            include_meta: true
          EOF          

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          distribution: goreleaser
          # 'latest', 'nightly', or a semver
          version: "~> v2"
          args: release --clean --verbose --config /tmp/goreleaser-github.yaml
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Upload .deb artifact x86
        uses: actions/upload-artifact@v3
        with:
          name: deb-package
          path: dist/*amd64.deb

  pkgcld_amd64-deb:
    runs-on: ubuntu-latest
    needs:
      - goreleaser
    strategy:
      max-parallel: 3
      matrix:
        distro:
        - debian/bookworm
        - ubuntu/noble
        - ubuntu/jammy
    steps:
      - name: Download .deb artifact
        uses: actions/download-artifact@v3
        with:
          name: deb-package

      - name: Push package to packagecloud.io
        uses: computology/[email protected]
        with:
          package-name: ./*.deb
          packagecloud-username: USERNAME
          packagecloud-reponame: APP_NAME
          packagecloud-distro: ${{ matrix.distro }}
          packagecloud-token: ${{ secrets.PACKAGECLOUD_TOKEN }}




ℹ️重要

您需要确保程序结构和 go.mod 文件等内容正确设置,否则您将在正确发布应用程序时遇到问题。

旁注:您还可以使用 Homebrew 分发您的应用程序,但我没有打扰,因为涉及 PAT 秘密的额外 GH 操作复杂性以及我已经很好地覆盖了 Apt好吃,还有炖菜……好吃! ?

这让我想到了发布应用程序时的第二件事。 ?文档? 以及备受忽视的 Readme.md?!

自述文件格式

我觉得任何像样的自述文件都应该具备一些元素,因为它们将帮助您的应用程序从所有几乎没有文档或更糟糕的文档的应用程序中脱颖而出。

我强烈建议您遵循这种格式来制作您自己的自述文件!我是天赋徽章的忠实粉丝,但我觉得有一个小 GIF 演示确实可以向人们展示它的含义,就像列出 GUI 应用程序的 屏幕截图 一样。使用 ASCIINEMA 非常简单,而且他们还有一个很好的 GIF 转换器,让一切看起来都恰到好处。

?提示

顺便说一句,我确实让 CodeGPT 给我写了一些 GoLang 单元测试,我知道编写这些测试通常很痛苦。如果您使用 JetBrains 套件,这是一个很棒的插件。

自述文件示例

  • 测试徽章
  • GIF 演示
  • 覆盖徽章
  • 去报告卡
  • 安装
    • 包管理器(ex apt)
    • 二进制安装(例如 eget)
    • 去安装片段
  • 用法
    • 清晰的说明和示例代码片段
  • 设置
    • 设置保存位置
    • 你使用 INI 文件、JSON、环境变量吗?
  • 如何访问内置帮助
  • 如何从源代码构建应用程序
  • 现有技术(又名以前的工作/灵感)

包起来

与我开始学习如何发布 Python 应用程序时类似,我很高兴能够说我觉得我可以正确分发我在 GoLang 中编写的任何应用程序。这是我学到的一项巧妙的技能,通过这篇博文,我希望它可以帮助其他人做同样的事情!干杯!

-Jelloeater


?乳齿象 | ?电子邮件 | ?评论 | ☕ 请我喝杯咖啡

版本聲明 本文轉載於:https://dev.to/jelloeater/publishing-cli-apps-with-apt-yum-568c?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • SOAP 與 REST API:了解主要差異
    SOAP 與 REST API:了解主要差異
    在 Web 服務領域,SOAP(簡單物件存取協定)和 REST(表述性狀態傳輸)是兩種廣泛使用的(soap 與 Rest API)架構。兩者都用作系統之間的通訊協議,但它們在設計、使用和性能方面存在顯著差異。了解這些差異對於開發人員和企業在選擇適合其需求的正確解決方案時至關重要。 什麼是 SOA...
    程式設計 發佈於2024-11-08
  • 如何使用 CSS 自訂文字下劃線顏色?
    如何使用 CSS 自訂文字下劃線顏色?
    使用 CSS 自訂文字下劃線顏色在網頁設計中,為文字添加下劃線是強調或突出顯示訊息的常見做法。但是,如果您想透過更改下劃線的顏色來添加獨特的觸感該怎麼辦?這可能嗎? 是的,可以使用 CSS 來變更文字下方線條的顏色。您可以使用以下兩種方法:方法 1:使用 text-decoration-color方...
    程式設計 發佈於2024-11-08
  • 在 JavaScript 中實現點擊劫持防禦技術
    在 JavaScript 中實現點擊劫持防禦技術
    点击劫持等复杂攻击的出现使安全成为当今网络世界的首要问题。通过欺骗消费者点击与他们最初看到的内容不同的内容,攻击者部署了一种名为“点击劫持”的邪恶方法,这可能会带来灾难性的后果。此类攻击有可能诱骗人们下载恶意软件、发送私人信息,甚至做他们无意的事情,例如购买任何东西。为了防止此类攻击,JavaScr...
    程式設計 發佈於2024-11-08
  • 為什麼我的浮動 Div 不調整後續 Div 的大小?
    為什麼我的浮動 Div 不調整後續 Div 的大小?
    Float 不調整Div 大小之謎當使用CSS float 時,假設後續元素將左對齊而不是流到新的元素上線。然而,在某些情況下,例如提供的範例,下面的 div 繼續跨越整個寬度,而不是從第一個 div 的右側開始。 為了理解這種行為,我們深入研究 float 的複雜性定位。當元素浮動時(在本例中為 ...
    程式設計 發佈於2024-11-08
  • 使用 PYTHON 將資料導入 MYSQL
    使用 PYTHON 將資料導入 MYSQL
    介紹 手動將資料匯入資料庫,尤其是當資料庫中有多個表格時,不僅很煩人,而且還很耗時。透過使用 python 庫可以使這變得更容易。 從kaggle下載繪畫資料集。繪畫資料集由 8 個 csv 檔案組成,我們將使用簡單的 python 腳本將其匯入到資料庫中,而不是手動將資料匯入到...
    程式設計 發佈於2024-11-08
  • MySQL 基本運算子及其應用
    MySQL 基本運算子及其應用
    MySQL 運算子是開發人員的關鍵工具,可實現精確的資料操作和分析。它們涵蓋了一系列功能,包括賦值、資料比較和複雜模式匹配。無論您是處理 JSON 資料還是根據條件過濾記錄,了解這些運算子對於高效的資料庫管理都至關重要。 本指南介紹了最重要的MySQL運算符,並透過實際範例示範如何使用它們,使開發...
    程式設計 發佈於2024-11-08
  • 如何測驗 Cron 作業:完整指南
    如何測驗 Cron 作業:完整指南
    Cron 作业在许多系统中对于调度任务、自动化流程和按指定时间间隔运行脚本至关重要。无论您是维护 Web 服务器、自动备份还是运行例行数据导入,cron 作业都能让您的操作顺利运行。但与任何自动化任务一样,它们必须经过彻底测试以确保可靠性和准确性。 在本文中,我们将探讨如何有效地测试 cron 作...
    程式設計 發佈於2024-11-08
  • Next.js 中間件簡介:它如何運作並提供範例
    Next.js 中間件簡介:它如何運作並提供範例
    我們來談談Nextjs中的路由。今天,我們來談談最強大的事物中間件之一。 Nextjs 中的中間件提供了一種強大且靈活的方法來攔截來自伺服器的請求並控制請求流(重定向、URL 重寫)並全域增強身份驗證、標頭、cookie 持久性等功能。 建立中介軟體 讓我們建立 Middlewar...
    程式設計 發佈於2024-11-08
  • 道具基礎:第 1 部分
    道具基礎:第 1 部分
    這是一個關於如何使用道具的初學者友好教學。在閱讀之前了解什麼是解構以及如何使用/創建元件非常重要。 Props,properties的縮寫,props允許我們從父元件向子元件發送訊息,還需要注意的是它們可以是任何資料類型。 必須了解為任何元件建立 prop 的語法。在 React 中,您必須使用...
    程式設計 發佈於2024-11-08
  • Hibernate 與 Spring Boot 有何不同?
    Hibernate 與 Spring Boot 有何不同?
    Hibernate 與 Spring Boot 有何不同? Hibernate 和 Spring Boot 都是 Java 生態系中流行的框架,但它們有不同的用途並具有不同的功能。 休眠 Hibernate 是一個物件關聯映射 (ORM) 框架,它允許開發人員使用...
    程式設計 發佈於2024-11-08
  • C++ 如何處理十進位資料型別?
    C++ 如何處理十進位資料型別?
    C 中的十進位資料型別 C 提供了各種資料型別來處理數值,但令人驚訝的是,十進位資料型別本身不支援。在處理精確的十進制值或與使用十進制格式的系統互動時,這可能是一個限制。 實作選項雖然 C 不提供內建十進位類型,但有兩種與他們合作的方法:1。 C Decimal TR 擴充:某些編譯器(例如gcc)...
    程式設計 發佈於2024-11-08
  • 為什麼我的 Python 中的凱撒密碼函數只顯示最後一個移位的字元?
    為什麼我的 Python 中的凱撒密碼函數只顯示最後一個移位的字元?
    Python 中的凱撒密碼函數:加密字串在Python 中實作凱撒密碼函數時,會出現一個常見問題,即最終的加密文字僅顯示最後移動的字元。要解決此問題,有必要了解導致此行為的問題。 在提供的程式碼中,循環迭代明文中的每個字元。對於字母字符,它根據提供的移位值來移位字符的 ASCII 代碼。但是,每個移...
    程式設計 發佈於2024-11-08
  • 4 快速​​部署PHP
    4 快速​​部署PHP
    Servbay 已成為輕鬆配置開發環境的首要工具。在本指南中,我們將示範如何快速、安全地部署 PHP 8.2,強調 Servbay 致力於簡化部署流程。 先決條件 開始之前,請確保您的裝置上安裝了 Servbay。您可以直接從Servbay官方網站下載。安裝直覺;只需按照提示操作,...
    程式設計 發佈於2024-11-08
  • AngularJS 指令中的 Replace 屬性何時被棄用?
    AngularJS 指令中的 Replace 屬性何時被棄用?
    為什麼AngularJS 已棄用指令中的替換屬性AngularJS 指令中的替換屬性由於其複雜性和更好的出現而被棄用替代方案。根據官方 AngularJS API 文檔,在未來的版本中它將預設為 false。 棄用的原因AngularJS 團隊發現了替換屬性的幾個問題:困難的語義: 它導致了屬性合併...
    程式設計 發佈於2024-11-08
  • 如何在 JavaScript 和 jQuery 中無縫存取 PHP 變數?
    如何在 JavaScript 和 jQuery 中無縫存取 PHP 變數?
    在JavaScript 或jQuery 中存取PHP 變數:避免Echo 過載許多開發人員遇到在JavaScript 和jQuery 中存取PHP 變數的挑戰。傳統方法涉及回顯 PHP 標籤內的變量,例如:<?php echo $variable1; ?> <?php echo $...
    程式設計 發佈於2024-11-08

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3