GitHub Action for Updating Your Readme with a Download Button
Tags: actionshackathon21, productivity, github
Published: 2021-12-06 01:37:41

[Instructions]: # (To submit to the GitHub Actions x DEV Hackathon 2021, please fill out all sections.)


### My Workflow
[Note]: # (Please make sure the project links to the appropriate GitHub Actions repository, and includes [an open source license](https://choosealicense.com/) and README.)

[**Readme Download Button Action**](https://github.com/DenverCoder1/readme-download-button-action) is a new workflow that allows you to keep a direct download link of the latest version of your repo in your README file.

Example download button generated by the workflow:

[![Download zip](https://custom-icon-badges.herokuapp.com/badge/-Download-blue?style=for-the-badge&logo=download&logoColor=white "Download zip")](https://github.com/DenverCoder1/readme-download-button-action/archive/1.0.1.zip)

The steps for setting up the workflow are explained in detail on the [GitHub repository](https://github.com/DenverCoder1/readme-download-button-action/).

#### Getting started

```yml
name: "Download Button Action"
on:
  release:
    types:
      - published
  workflow_dispatch:
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Get latest release
        id: get-latest-release
        uses: InsonusK/get-latest-release@v1.0.1
        with:
          myToken: ${{ github.token }}
          view_top: 1
      - name: Readme Download Button Action
        env:
          GITHUB_USER: "DenverCoder1"
          REPO: "readme-download-button-action"
          FORMAT: "zip"
          VERSION: "${{ steps.get-latest-release.outputs.tag_name }}"
          COLOR: "blue"
          BEGIN_TAG: "<!-- BEGIN LATEST DOWNLOAD BUTTON -->"
          END_TAG: "<!-- END LATEST DOWNLOAD BUTTON -->"
        run: |
          UPDATE=$(cat README.md | perl -0777 -pe 's#(${{ env.BEGIN_TAG }})(?:.|\n)*?(${{ env.END_TAG }})#${1}\n[![Download ${{ env.FORMAT }}](https://custom-icon-badges.herokuapp.com/badge/-Download-${{ env.COLOR }}?style=for-the-badge&logo=download&logoColor=white "Download ${{ env.FORMAT }}")](https://github.com/${{ env.GITHUB_USER }}/${{ env.REPO }}/archive/${{ env.VERSION }}.${{ env.FORMAT }})\n${2}#g')
          echo "${UPDATE}" > README.md
      - uses: EndBug/add-and-commit@v7
        with:
          message: "docs(readme): Bump download button version to ${{ steps.get-latest-release.outputs.tag_name }}"
          default_author: github_actions
          branch: main
```

### Submission Category:

[Note]: # (Maintainer Must-Haves, DIY Deployments, Interesting IoT, Phone Friendly, or Wacky Wildcards)

Maintainer Must-Haves

### Yaml File or Link to Code

[Note]: # (Our markdown editor supports pretty embeds. Try this syntax: `{% github link_to_your_repo %}` to share a GitHub repository)

{% github DenverCoder1/readme-download-button-action %}

### Background

This project was created due to the fact that many users may come to a repository to download a project but are not familiar enough with the site to navigate the repository and find a proper download link.

This workflow aims to simplify the process, by putting a download button front and center in the Readme so it can't be missed.

Having a download button on the Readme allows visiting users to quickly download your source code with **just a single click**!

**Why does this require a workflow?**

In order to make the process a single click away, a direct download link must be included.

For example, a link to download the source code of version 1.0.1 of [readme-download-button-action](https://github.com/DenverCoder1/readme-download-button-action) will look like this: `https://github.com/DenverCoder1/readme-download-button-action/archive/1.0.1.zip`.

Notice that the url contains **1.0.1**, the *version*. This number changes with every new version released, so in order to keep the download button up-to-date, we will have to update the readme to change the link.

That's where this workflow comes in. With just a few seconds of one-time configuration, your button will be generated and automatically kept up to date whenever you make a new release.

### Making of this workflow

First, we need to set the trigger event. A good choice here is when we publish a release. Additionally `workflow_dispatch:` is added so that it can be manually triggered from the Actions tab in case you want to re-run it without creating a new release.

```yml
on:
  release:
    types:
      - published
  workflow_dispatch:
```

Next, we create some steps:

**Checkout**

In order to be able to read and overwrite the files in the repo such as the readme, we will need to first checkout the repository.

```yml
- uses: actions/checkout@v2
```

**Get Latest Release**

The following workflow by InsonusK allows us to get info on the latest release. We can access the tag name later using `${{ steps.get-latest-release.outputs.tag_name }}`

```yml
- name: Get latest release
  id: get-latest-release
  uses: InsonusK/get-latest-release@v1.0.1
  with:
    myToken: ${{ github.token }}
    view_top: 1
```

**The custom shell script**

The actual replacement of the button is done with a shell step:

```yml
- name: Readme Download Button Action
  env:
    GITHUB_USER: "DenverCoder1"
    REPO: "readme-download-button-action"
    FORMAT: "zip"
    VERSION: "${{ steps.get-latest-release.outputs.tag_name }}"
    COLOR: "blue"
    BEGIN_TAG: "<!-- BEGIN LATEST DOWNLOAD BUTTON -->"
    END_TAG: "<!-- END LATEST DOWNLOAD BUTTON -->"
  run: |
    UPDATE=$(cat README.md | perl -0777 -pe 's#(${{ env.BEGIN_TAG }})(?:.|\n)*?(${{ env.END_TAG }})#${1}\n[![Download ${{ env.FORMAT }}](https://custom-icon-badges.herokuapp.com/badge/-Download-${{ env.COLOR }}?style=for-the-badge&logo=download&logoColor=white "Download ${{ env.FORMAT }}")](https://github.com/${{ env.GITHUB_USER }}/${{ env.REPO }}/archive/${{ env.VERSION }}.${{ env.FORMAT }})\n${2}#g')
    echo "${UPDATE}" > README.md
```

`perl` is used here to make a multiline replacement using regular expressions. At first I was going to try `sed` but it deals with lines one at a time, so it's much more complicated when dealing with multiline matches.

An `env` section also appears to make configuring the download button as simple as possible.

**Add and commit**

Finally we can use EndBug's add-and-commit to make the change persist!

```yml
- uses: EndBug/add-and-commit@v7
  with:
    message: "docs(readme): Bump download button version to ${{ steps.get-latest-release.outputs.tag_name }}"
    default_author: github_actions
    branch: main
```

### Additional Resources / Info

[Note]: # (Be sure to link to any open source projects that are using your workflow!)

[Note]: # (Be sure to include the DEV usernames of your collaborators, if any. )

[Reminder]: # (Submissions are due on December 8th, 2021 (11:59 PM PT or 2 AM ET/6 AM UTC on December 9th. )

This action works great in combination with several open-source workflows:

- [InsonusK/get-latest-release](https://github.com/InsonusK/get-latest-release) - Determine the tag for the latest release
- [EndBug/add-and-commit](https://github.com/EndBug/add-and-commit) - Commit your changes
- [tvdias/github-tagger](https://github.com/tvdias/github-tagger) - Create new tags to push to
- [fregante/release-with-changelog](https://github.com/fregante/release-with-changelog) - generate changelogs for your releases