From 29d55a74f8399a38632bc23acb6774a330d375bd Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Sun, 4 Feb 2024 17:22:13 -0300 Subject: [PATCH] docs(blog): import more posts refs #3503 Signed-off-by: Carlos Alexandro Becker --- .../posts/2022-02-05-cloud-native-storage.md | 316 ++++++++++++++ .../blog/posts/2022-02-20-azure-devops.md | 402 ++++++++++++++++++ .../blog/posts/2022-03-07-homebrew-gofish.md | 133 ++++++ 3 files changed, 851 insertions(+) create mode 100644 www/docs/blog/posts/2022-02-05-cloud-native-storage.md create mode 100644 www/docs/blog/posts/2022-02-20-azure-devops.md create mode 100644 www/docs/blog/posts/2022-03-07-homebrew-gofish.md diff --git a/www/docs/blog/posts/2022-02-05-cloud-native-storage.md b/www/docs/blog/posts/2022-02-05-cloud-native-storage.md new file mode 100644 index 000000000..423eb0af0 --- /dev/null +++ b/www/docs/blog/posts/2022-02-05-cloud-native-storage.md @@ -0,0 +1,316 @@ +--- +date: 2022-02-05 +slug: cloud-native-storage +categories: + - tutorials +authors: + - dirien +--- + +# How to use GoReleaser with Cloud Native Storage + +In this tutorial, I want to describe, how quickly we can deploy our release +artefacts to a cloud native storage when using GoReleaser. +It’s just a few additional lines in your `.goreleaser.yaml`. + + + +To better show this, I created a little demo and use the storage services of the +big three cloud providers: Azure Blob Storage, AWS S3 and Google Cloud Storage. + +![](https://cdn-images-1.medium.com/max/2000/1*4kvgGvBM9--v2rS7nO5c1g.png) + +You can use any S3 compatible storage provider too. +**GoReleaser** support this too! The most prominent (self-hosted) solution is +**MinIO**. + +![](https://cdn-images-1.medium.com/max/4802/1*SH5PQKBDEB0M8mAY7EONeQ.png) + +## The infrastructure code + +I created a very simple **Terraform** deployment to provision on all three cloud +provider their appropriate cloud storage service. +It’s a demo, why not? + +You don’t need to use **Terraform** for this, you could use any other means like +**Pulumi**, **CLI** or even the **UI**. + +###### `main.tf` + +```terraform +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "4.9.0" + } + azurerm = { + source = "hashicorp/azurerm" + version = "2.94.0" + } + aws = { + source = "hashicorp/aws" + version = "3.74.0" + } + } +} + +provider "azurerm" { + features {} +} + +provider "google" { + credentials = file(var.gcp_auth_file) + project = var.gcp_project + region = var.gcp_region +} + +provider "aws" { + region = var.aws_region +} +``` + +###### `variables.tf` + +```terraform +variable "gcp_project" { + type = string +} + +variable "gcp_region" { + default = "europe-west6" +} + +variable "gcp_zone" { + default = "europe-west6-a" +} + +variable "gcp_bucket_location" { + default = "EU" +} + +variable "gcp_auth_file" { + default = "./auth.json" + description = "Path to the GCP auth file" +} + +variable "aws_region" { + default = "eu-central-1" +} + +variable "azure_location" { + default = "West Europe" +} + +variable "name" { + default = "gorleaser-quickbites" +} +``` + +###### `blob.tf` + +```terraform +resource "google_storage_bucket" "goreleaser-gcp-storage-bucket" { + name = var.name + location = var.gcp_bucket_location + force_destroy = true + uniform_bucket_level_access = false +} +resource "google_storage_bucket_access_control" "goreleaser-gcp-storage-bucket-access-control" { + bucket = google_storage_bucket.goreleaser-gcp-storage-bucket.name + role = "READER" + entity = "allUsers" +} + +resource "azurerm_resource_group" "goreleaser-azure-resource-group" { + name = var.name + location = var.azure_location +} + +resource "azurerm_storage_account" "goreleaser-azure-storage-account" { + name = "gorleaserquickbites" + resource_group_name = azurerm_resource_group.goreleaser-azure-resource-group.name + location = azurerm_resource_group.goreleaser-azure-resource-group.location + account_tier = "Standard" + account_replication_type = "LRS" + allow_blob_public_access = true + network_rules { + default_action = "Allow" + } +} + +resource "azurerm_storage_container" "goreleaser-storage-container" { + name = var.name + storage_account_name = azurerm_storage_account.goreleaser-azure-storage-account.name + container_access_type = "container" +} + +resource "aws_s3_bucket" "goreleaser-s3-bucket" { + bucket = var.name + acl = "public-read" +} +``` + +###### Apply the Terraform script: + +```bash +terraform apply -var "gcp_project=xxx" +``` + +``` +... +azurerm_storage_container.goreleaser-storage-container: Creation complete after 0s [id=https://gorleaserquickbites.blob.core.windows.net/gorleaser-quickbites] + +Apply complete! Resources: 6 added, 0 changed, 0 destroyed. + +Outputs: + +aws-s3-bucket-name = "gorleaser-quickbites" +azure-storage-account-key = +azure-storage-account-name = "export AZURE_STORAGE_ACCOUNT=gorleaserquickbites" +gcp-bucket-url = "gs://gorleaser-quickbites" +``` + +###### Run this command + +```bash +terraform output azure-storage-account-key +``` + +to get the Azure Storage Account Key, as it is a output field with sensitive data in it. + +```bash +export AZURE_STORAGE_KEY=xxxx +``` + +Now we can add in our `.goreleaser.yaml` the new **blobs** field. +Important is here to set the right provider: **gs** (for Google Cloud Storage), +**azblob** (for Azure Blob) and **s3** (for AWS S3 or compatible provider)! + +```yaml +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +before: + hooks: + - go mod tidy +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + +release: + disable: true +--- +blobs: + - provider: gs + bucket: gorleaser-quickbites + - provider: azblob + bucket: gorleaser-quickbites + - provider: s3 + bucket: gorleaser-quickbites + region: eu-central-1 +``` + +In this demo, I disabled the **release **section, as I don’t want to upload to +GitHub. + +## Authentication + +In terms of authentication the GoReleaser’s blob pipe authentication varies depending upon the blob provider as mentioned below: + +### S3 Provider + +S3 provider support AWS [default credential +provider](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials) +chain in the following order: + +- Environment variables. +- Shared credentials file. +- If your application is running on an Amazon EC2 instance, IAM role for Amazon EC2. + +### Azure Blob Provider Currently it supports authentication only + +with [environment variables](https://docs.microsoft.com/en-us/azure/storage/common/storage-azure-cli#set-default-azure-storage-account-environment-variables): + +- AZURE_STORAGE_ACCOUNT +- AZURE_STORAGE_KEY or AZURE_STORAGE_SAS_TOKEN + +### GCS + +Provider GCS provider uses [Application Default +Credentials](https://cloud.google.com/docs/authentication/production) in the +following order: + +- Environment Variable (GOOGLE_APPLICATION_CREDENTIALS) +- Default Service Account from the compute instance (Compute Engine, Kubernetes + Engine, Cloud function etc). + +## Run GoReleaser + +After configuring we can finally execute **GoReleaser**, in your pipeline code +via the command: + +```bash +goreleaser release --rm-dist +``` + +If everything went smooth, you should see a similar output, showing the upload of your artefacts. + +``` + ... + • publishing + • blobs + • uploading path=quick-bites/0.1/quick-bites_0.1_checksums.txt + • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_amd64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_arm64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_arm64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_amd64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_386.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_checksums.txt + • uploading path=quick-bites/0.1/quick-bites_0.1_checksums.txt + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_386.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_amd64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_arm64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_amd64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_amd64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_arm64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_386.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_linux_arm64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_arm64.tar.gz + • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_amd64.tar.gz + • release succeeded after 22.63s + ... +``` + +> One note: The provider fails silently, if your credentials are wrong. You +> would still see uploading and release succeeded. Keep this in mind, if the +> files are not appearing in the UI. I wasted some time on this. The culprit is +> the underlying library GoReleaser is using. + +Let’s check in the consoles of the cloud provider too, If the files are present. + +###### Google Cloud Storage: + +![Google Cloud Storage](https://cdn-images-1.medium.com/max/2468/1*OHPaMIOK2YP7HsdgXEPpSw.png) + +###### Azure Blob Storage + +![Azure Blob Storage](https://cdn-images-1.medium.com/max/2792/1*K0BMoKe2qH29YHCOtZ8e9A.png) + +###### AWS S3 + +![AWS S3](https://cdn-images-1.medium.com/max/2868/1*mvgyZMWtZseRabusw_R4Dg.png) + +Looks very good! Now you can share the URLs of the files for further use! + +## Want more Informations? + +If you want to know more about some advanced options, feel free to check out the +[official documentation about the blob support in +GoReleaser](https://goreleaser.com/customization/blob/) + +And here is the example code: [dirien/quick-bytes](https://github.com/dirien/quick-bites/tree/main/goreleaser-blob) + +![Have fun](https://cdn-images-1.medium.com/max/2000/0*kbicxfar7Vo9rUon.jpg) diff --git a/www/docs/blog/posts/2022-02-20-azure-devops.md b/www/docs/blog/posts/2022-02-20-azure-devops.md new file mode 100644 index 000000000..b1ff565a8 --- /dev/null +++ b/www/docs/blog/posts/2022-02-20-azure-devops.md @@ -0,0 +1,402 @@ +--- +date: 2022-02-20 +slug: azure-devops +categories: + - tutorials +authors: + - dirien +--- + +# Use GoReleaser With Azure DevOps + +In this blog article, I want to show how to use **GoReleaser** in **Azure DevOps**. + + + +![](https://cdn-images-1.medium.com/max/2000/1*hAK9NMa-YbSnTQdSEoX7Gw.png) + +In this blog article, I want to show how to use **GoReleaser** in **Azure +DevOps**. + +### But why? Are not everyone using GitHub? + +Exactly, not everyone is using GitHub. Actually, there are many companies who +use the Azure Cloud with **Azure DevOps**. + +## What is Azure DevOps? + +**Azure DevOps** provides developer services for allowing teams to plan work, +collaborate on code development, and build and deploy applications. + +**Azure DevOps** provides integrated features that you can access through your +web browser or IDE client. You can use one or more of the following standalone +services based on your business needs: + +- **Azure Repos** provides Git repositories. +- **Azure Pipelines** provides build and release services to support continuous + integration and delivery of your applications. +- **Azure Boards** delivers a suite of Agile tools to support planning and + tracking work, code defects, and issues using Kanban and Scrum methods. +- **Azure Test Plans** provides several tools to test your apps, including + manual/exploratory testing and continuous testing. +- **Azure Artifacts** allows teams to share packages such as Maven, npm, NuGet, + and more from public and private sources and integrate package sharing into your + pipelines. + +## Install GoReleaser Via The Marketplace + +![](https://cdn-images-1.medium.com/max/4144/1*NCY5i6iCEPW5ZpNhYeB6Jg.png) + +**GoReleaser** offers a [Plugin via the +Marketplace](https://marketplace.visualstudio.com/items?itemName=GoReleaser.goreleaser). +The installation itself is done via some clicks in the UI and you are ready to +start! + +In your pipeline editor you can lookup the task: + +![](https://cdn-images-1.medium.com/max/2000/1*U-zVyao5qwgjfzTcGHgSJA.png) + +And quickly change the default settings to fit with your use case! +For example set a specific version or execute certain **GoReleaser** commands. + +See the official docs for more details +[https://github.com/goreleaser/goreleaser-azure-devops-extension](https://github.com/goreleaser/goreleaser-azure-devops-extension) + +![](https://cdn-images-1.medium.com/max/2000/1*Aqtx-0KvADotNmeX7X1HTQ.png) + +## Finally The Demo! + +```go +package main + +import ( + "fmt" +) + +var ( + version = "0.0.1" + commit = "none" + date = "none" + builtBy = "none" +) + +func main() { + fmt.Println("Version:\t", version) + fmt.Println("Commit:\t\t", commit) + fmt.Println("Date:\t\t", date) + fmt.Println("Built by:\t", builtBy) +} +``` + +Before we head over to the configure the pipeline, let us create the +`.goreleaser.yaml` + +```yaml +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy +builds: + - env: + - CGO_ENABLED=0 + goarch: + - amd64 + - arm64 + goos: + - linux + - darwin + +project_name: goreleaser-ado + +checksum: + name_template: "checksums.txt" + +snapshot: + name_template: "{{ incpatch .Version }}-next" + +source: + enabled: true + +release: + disable: true + +sboms: + - artifacts: archive + - id: source + artifacts: source + +signs: + - cmd: cosign + certificate: "${artifact}.pem" + args: + - sign-blob + - "-key=cosign.key" + - "--output-certificate=${certificate}" + - "--output-signature=${signature}" + - "${artifact}" + artifacts: checksum + output: true + stdin: "{{ .Env.COSIGN_PASSWORD }}" + +docker_signs: + - cmd: cosign + artifacts: images + output: true + args: + - "sign" + - "-key=cosign.key" + - "${artifact}" + stdin: "{{ .Env.COSIGN_PASSWORD }}" + +dockers: + - image_templates: ["dirien/{{ .ProjectName }}:{{ .Version }}-amd64"] + goarch: amd64 + dockerfile: Dockerfile + use: buildx + build_flag_templates: + - --platform=linux/amd64 + - image_templates: ["dirien/{{ .ProjectName }}:{{ .Version }}-arm64"] + goarch: arm64 + dockerfile: Dockerfile + use: buildx + build_flag_templates: + - --platform=linux/arm64/v8 + +docker_manifests: + - name_template: "dirien/{{ .ProjectName }}:{{ .Version }}" + image_templates: + - "dirien/{{ .ProjectName }}:{{ .Version }}-amd64" + - "dirien/{{ .ProjectName }}:{{ .Version }}-arm64" + - name_template: "dirien/{{ .ProjectName }}:latest" + image_templates: + - "dirien/{{ .ProjectName }}:{{ .Version }}-amd64" + - "dirien/{{ .ProjectName }}:{{ .Version }}-arm64" +``` + +Here, we going to create **linux** and **darwin** binary, the corresponding +container, create the SBoM with syft and sign everything via cosign. + +> Here is one first important steps: you need to disable the **release** step in +> GoReleaser. +> Azure DevOps does not work the same way as GitHub what releases concerns. +> We handle the upload of the artefacts differently. + +If you need more infos, for the different settings and possibilities inside +**GoReleaser**, head over to the official documentation +[https://goreleaser.com/intro/](https://goreleaser.com/intro/) + +### Service + +Connection in Azure DevOps As we going to upload the image to Docker Hub, we +need to create in **Azure Devops** the Service Connection. + +Go to **Project Settings** and click **Service connections**: +![](https://cdn-images-1.medium.com/max/2000/1*QDD9dVR5ZYUtm4qh5Izy2w.png) +![](https://cdn-images-1.medium.com/max/2000/1*PMGoYUHoda1bVumVGW1Fow.png) + +Choose **Docker Registry**: +![](https://cdn-images-1.medium.com/max/2000/1*JmkHy2p5pjhc7llWCHjChw.png) + +In the detail view, select **Docker Hub **and then enter your details, like +**Docker ID**, **Docker Password** and the **Service Connection Name**: +![](https://cdn-images-1.medium.com/max/2000/1*WCT6xaaNtoT6Y-Ws7-0qOQ.png) + +Click **Verify and save**, we will come back to the service connection in our +Pipeline code. + +### The Azure Pipeline File + +Now starts the fun part, the creation of the actual Azure Pipeline. +If you are completely new to **Azure DevOps** pipeline, I highly suggest to +checkout the +[docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/create-first-pipeline?view=azure-devops&tabs=java%2Ctfs-2018-2%2Cbrowser) +from Microsoft. + +In our example, we going to write the pipeline only as code (there is a +deprecated UI only option too! But meh!). + +Azure Pipeline are written in **yaml.** + +```yaml +# Starter pipeline +# Start with a minimal pipeline that you can customize to build and deploy your code. +# Add steps that build, run tests, deploy, and more: +# https://aka.ms/yaml + +pr: + branches: + include: + - main + +trigger: + tags: + include: + - "*" + branches: + include: + - "*" + +jobs: + - job: build + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go" + inputs: + version: "1.17" + - task: CmdLine@2 + displayName: "Build and Test" + inputs: + script: | + go mod tidy + go build . + - job: release + dependsOn: build + displayName: Release via GoReleaser + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/')) + variables: + - group: cosign + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go" + inputs: + version: "1.17" + - task: CmdLine@2 + displayName: "Install Syft" + inputs: + script: | + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin + - task: CmdLine@2 + displayName: "Install cosign" + inputs: + script: | + curl -sLO https://github.com/sigstore/cosign/releases/download/v1.5.2/cosign-linux-amd64 + chmod +x cosign-linux-amd64 + mv cosign-linux-amd64 /usr/local/bin/cosign + - task: Docker@2 + inputs: + containerRegistry: "dirien-docker-hub" + command: "login" + addPipelineData: false + addBaseImageData: false + - task: goreleaser@0 + inputs: + version: "latest" + distribution: "goreleaser" + args: "release --rm-dist" + + - task: CopyFiles@2 + displayName: "Copy GoReleaser dist folder to ArtifactStagingDirectory" + inputs: + Contents: | + dist/*.tar.gz + dist/*.zip + dist/*.txt + dist/*.sbom + dist/*.sig + cosign.pub + TargetFolder: "$(Build.ArtifactStagingDirectory)" + CleanTargetFolder: true + OverWrite: true + flattenFolders: true + + - task: PublishBuildArtifacts@1 + displayName: "Publish GoReleaser release artifacts" + inputs: + ArtifactName: "GoReleaser release" +``` + +The pipeline consist of two different jobs parts: + +- the **build** job, run every time something changes on any branch or when a + pull request gets created. Here we can run our tests, linting, SAST to get + quickly feedback. +- the **release** job, will run only when a git tag gets created (see the + condition tag under the job tag). Creating a git tag is part of the release + process. Similar as we do in the GitHub Flow. + +During the release job, we download [Anchore +syft](https://github.com/anchore/syft) and +[cosign](https://github.com/sigstore/cosign) as we going to need them during the +**gorleaser** task. +Currently there is no native task for this in **Azure DevOps**. We just use the +**CmdLine** task and curl the binaries. + +![](https://cdn-images-1.medium.com/max/2496/1*O01UvqQCv8255Kj9JEvxiw.png) + +It is also important to log into your **Docker Hub** account, via the **Service +Connection** we created earlier. +The **Docker** task takes care of the actual login. + +![](https://cdn-images-1.medium.com/max/2000/1*_uMeZymqEJ0Xqq64OP_UXA.png) + +Now we can call our **GoReleaser** task. + +![](https://cdn-images-1.medium.com/max/2000/1*blEbdGwd8PXZ9ExCScfYtw.png) + +### Azure Pipeline Secret Library + +For cosign, I use a password, I stored in the Azure Pipeline Library as secret +variable. + +![](https://cdn-images-1.medium.com/max/4028/1*ioSS8X6yT4qFNQrCrQbAYA.png) + +In my pipeline code, I will pass this value as environment variable via the +variables tag. + +![](https://cdn-images-1.medium.com/max/2000/1*CTox6hgrOCgaTs9AFJWUhQ.png) + +In this demo, I am going to publish the release artefacts as build artefacts. + +![](https://cdn-images-1.medium.com/max/2244/1*nwH4Ej9GbQ6RdE_MfYMelw.png) + +The task **CopyFiles** collects some files from the **dist** folder and the +cosign public key and **PublishBuildArtifacts** publish them. +You will find the artefacts on the pipeline detail + +![](https://cdn-images-1.medium.com/max/2000/1*GWCiLGBnHOnCjyRuqrPEEw.png) + +![](https://cdn-images-1.medium.com/max/4220/1*MLeku1FpKCFMv7bfNvu_eA.png) + +Of course, you can use other targets too, like a cloud native storage. + +You can check out the +[How to use GoReleaser with Cloud Native +Storage](https://blog.goreleaser.com/how-to-use-goreleaser-with-cloud-native-storage-bbc4bee5fe91) +post for more details on this subject + +### Release the kraken äh app! + +Head over to **tags** menu and create a new tag in the UI + +![](https://cdn-images-1.medium.com/max/2000/1*zIYaYhDk1rSpd5_si5mHIA.png) + +![](https://cdn-images-1.medium.com/max/4472/1*Zaq4EUjn3egC5_3VLVQA5Q.png) + +Your pipeline should immediately start to run: + +![](https://cdn-images-1.medium.com/max/5528/1*h5YYGAPjIXrcympI01H9yA.png) + +And both jobs should run: + +![](https://cdn-images-1.medium.com/max/5592/1*TawbQohuoGdG4sO9xo0YLw.png) + +![](https://cdn-images-1.medium.com/max/2000/0*GY5jcM6UErG39iF2.jpg) + +And this is pretty much all of it! As I promised, very easy and straight forward +we can implement **GoReleaser** in **Azure DevOps**, similar we would use it in +GitHub + +![](https://cdn-images-1.medium.com/max/2560/0*1ZhRSdH-Se88gOdj.jpg) + +### Caveat: + +- I use in cosign not the + [keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) approach, as + I am not sure that it will work for **Azure DevOps**. So I generated a keypair + and committed the public and private key into the repository. diff --git a/www/docs/blog/posts/2022-03-07-homebrew-gofish.md b/www/docs/blog/posts/2022-03-07-homebrew-gofish.md new file mode 100644 index 000000000..301d6cda4 --- /dev/null +++ b/www/docs/blog/posts/2022-03-07-homebrew-gofish.md @@ -0,0 +1,133 @@ +--- +date: 2022-03-07 +slug: homebrew-gofish +categories: + - tutorials +authors: + - dirien +--- + +# GoReleaser: How To Distribute Your Binaries With Homebrew Or GoFish + +This article is going to be a quick bite (or drink)! We going to discover, how +fast we can create a **Homebrew** or **GoFish** deployment of our binaries with +the help of **GoReleaser**. + + + +But first, let us take a look into the concepts of the two package managers: + +### **Homebrew **🍺 + +> The Missing Package Manager for macOS (or Linux) + +This statement is not from me, but from the official +[Homebrew](https://brew.sh/) website. **Homebrew** is similar to other package +managers, like [apt-get](https://wiki.debian.org/apt-get), +[aptitude](https://wiki.debian.org/Aptitude), or +[dpkg](https://wiki.debian.org/dpkg). I will not go in this article into the +details about **Homebrew**, but some terms are important to understand, as we +going to use them in our `.goreleaser.yaml` file: + +**Tap:** A Git repository of packages. + +**Formula**: A software package. When we want to install new programs or +libraries, we install a formula. + +### GoFish 🐠 + +> GoFish, the Package Manager 🐠 + +[GoFish](https://gofi.sh/) is a cross-platform systems package manager, bringing +the ease of use of Homebrew to Linux and Windows. Same as with **Homebrew**, I +am not going into detail of **GoFish** but we need also here some understanding +of the **GoFish** terminology: + +**Rig:** A git repository containing fish food. + +**Food:** The package definition + +### The example code + +For each package manager, you should create its own GitHub repository. You can +name it as you please, but i prefer to add the meaning of the repository. + +- **goreleaser-rig** for GoFish +- **goreleaser-tap** for Homebrew + +Add following snippet for **GoFish** support, to your existing +`.goreleaser.yaml`: + +```yaml +rigs: + - rig: + owner: dirien + name: goreleaser-rig + homepage: "https://github.com/dirien/quick-bites" + description: "Different type of projects, not big enough to warrant a separate repo." + license: "Apache License 2.0" +``` + +And for **Homebrew**, add this little snippet: + +```yaml +brews: + - tap: + owner: dirien + name: goreleaser-tap + folder: Formula + homepage: "https://github.com/dirien/quick-bites" + description: "Different type of projects, not big enough to warrant a separate repo." + license: "Apache License 2.0" +``` + +That’s all for now, and as usual with GoReleaser you can head over to the great +documentation for more advanced settings: + +> [https://goreleaser.com](https://goreleaser.com/intro/) + +Now run the release process and you will see this in your logs: + +``` + • homebrew tap formula + • pushing formula=Formula/goreleaser-brew-fish.rb repo=dirien/goreleaser-tap + • gofish fish food cookbook + • pushing food=Food/goreleaser-brew-fish.lua repo=dirien/goreleaser-rig +``` + +Perfect! Everything works as expected. + +We can check the content on the GitHub UI. + +![](https://cdn-images-1.medium.com/max/5964/1*O2zfXri4yrmo_GN3clczow.png) + +![](https://cdn-images-1.medium.com/max/6020/1*1TVV84tYM1staeDcifH7tw.png) + +### Installation + +Now we can add the tap and the rig on our clients + +**Homebrew** + +```bash +brew tap dirien/goreleaser-tap +brew install goreleaser-brew-fish +``` + +**GoFish** + +```bash +gofish rig add https://github.com/dirien/goreleaser-rig +gofish install github.com/dirien/goreleaser-rig/goreleaser-brew-fish +``` + +### The End + +Now you can distribute this tap or rig repositories and everybody can install your projects via this package manager. + +![](https://cdn-images-1.medium.com/max/2560/0*prjIhehAsUYTBaLx.jpg) + +### The Code + +You can find the demo code in my repository, to see some more details: +[dirien/quick-bites](https://github.com/dirien/quick-bites/tree/main/goreleaser-brew-fish).