From 550ce5cb000077c8910460c3dd8c4b69ab537b0c Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Fri, 8 Dec 2023 01:51:34 +0000 Subject: [PATCH] build: automatically upload and publish to the chrome store (#45) * ci: add new action to download the asset from the latest release * ci: add workflow to upload and publish to chrome store * docs: add all new badges to the readme * chore: squash --- .../download-latest-release-asset/action.yml | 19 +++ .../workflows/publish_to_chrome_web_store.yml | 30 +++++ README.md | 32 ++++- bin/get_latest_release_asset.sh | 72 +++++++++++ bin/publish_to_chrome.sh | 118 ++++++++++++++++++ bin/update_issue_templates.sh | 2 +- 6 files changed, 268 insertions(+), 5 deletions(-) create mode 100644 .github/actions/download-latest-release-asset/action.yml create mode 100644 .github/workflows/publish_to_chrome_web_store.yml create mode 100755 bin/get_latest_release_asset.sh create mode 100755 bin/publish_to_chrome.sh diff --git a/.github/actions/download-latest-release-asset/action.yml b/.github/actions/download-latest-release-asset/action.yml new file mode 100644 index 00000000..b795039c --- /dev/null +++ b/.github/actions/download-latest-release-asset/action.yml @@ -0,0 +1,19 @@ +name: "Download Latest Release Asset" + +description: "Checks for the latest release and downloads the asset for the prefix." + +inputs: + asset_prefix: + description: "The asset prefix, ie. 'kibisis-chrome'" + required: true + github_token: + description: "GitHub token to use to get release" + required: true + +runs: + using: "composite" + steps: + - name: "📥 Get latest release asset" + run: | + GITHUB_TOKEN=${{ inputs.github_token }} ./bin/get_latest_release_asset.sh ${{ inputs.asset_prefix }} + shell: bash diff --git a/.github/workflows/publish_to_chrome_web_store.yml b/.github/workflows/publish_to_chrome_web_store.yml new file mode 100644 index 00000000..9217897e --- /dev/null +++ b/.github/workflows/publish_to_chrome_web_store.yml @@ -0,0 +1,30 @@ +name: "Publish To Chrome Web Store" + +on: + release: + types: [released] # triggered on main branch releases + +env: + asset_prefix: "kibisis-chrome" + +jobs: + deploy: + name: "Deploy" + needs: install + runs-on: ubuntu-latest + steps: + - name: "🛎 Checkout" + uses: actions/checkout@v3 + - name: "📥 Download Latest Release Asset" + uses: ./.github/actions/download-latest-release-asset + with: + asset_prefix: ${{ env.asset_prefix }} + github_token: ${{ secrets.WRITE_REPOS_TOKEN }} + - name: "🚀 Publish" + env: + CHROME_WEB_STORE_API_CLIENT_ID: ${{ secrets.CHROME_WEB_STORE_API_CLIENT_ID }} + CHROME_WEB_STORE_API_CLIENT_SECRET: ${{ secrets.CHROME_WEB_STORE_API_CLIENT_SECRET }} + CHROME_WEB_STORE_API_REFRESH_TOKEN: ${{ secrets.CHROME_WEB_STORE_API_REFRESH_TOKEN }} + run: | + ./bin/publish_to_chrome.sh ${{ secrets.CHROME_WEB_STORE_ID }} ${{ env.asset_prefix }}.zip + diff --git a/README.md b/README.md index 4f259c94..0741e790 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,35 @@

- - Pull Request Checks + + GitHub release - - Mozilla add-on + + GitHub Release Date - Published_At + +

+ +

+ + GitHub License + + + GitHub Release Date - Published_At + +

+ +

+ + Mozilla add-on + + + Chrome Web Store Version + +

+ +

+ + GitHub License

diff --git a/bin/get_latest_release_asset.sh b/bin/get_latest_release_asset.sh new file mode 100755 index 00000000..967c39d5 --- /dev/null +++ b/bin/get_latest_release_asset.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$(dirname "${0}") + +source "${SCRIPT_DIR}/set_vars.sh" + +# Public: Gets the latest release and downloads the asset for the supplied prefix. +# +# Required environment variables: +# * $GITHUB_TOKEN - a client ID for the Chrome Web Store API. +# +# $1 - The asset prefix, ie. "kibisis-chrome". +# +# Examples +# +# GITHUB_TOKEN=super_secret_token ./bin/get_latest_release_asset.sh "kibisis-chrome" +# +# Returns exit code 0 if successful, or 1 if the GitHub token is not supplied, the GitHub API is unauthorized or no +# prefix is supplied. +function main { + local latest_release_result + local asset_name + local asset_url + + set_vars + + # check if asset prefix is provided + if [ -z "${1}" ]; then + printf "%b no asset prefix provided, use: ./bin/get_latest_release_asset.sh [asset_prefix] \n" "${ERROR_PREFIX}" + exit 1 + fi + + # check if the github token is set + if [ -z "${GITHUB_TOKEN}" ]; then + printf "%b github token not provided \n" "${ERROR_PREFIX}" + exit 1 + fi + + printf "%b getting latest release asset... \n" "${INFO_PREFIX}" + + latest_release_result=$(curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + -s \ + "https://api.github.com/repos/agoralabs-sh/kibisis-web-extension/releases/latest") + + # check for errors + if [ $(jq 'has("message")' <<< "${latest_release_result}") == true ]; then + printf "%b failed to latest release asset url: $(jq '.message' <<< "${latest_release_result}") \n" "${ERROR_PREFIX}" + exit 1 + fi + + asset_name=$(jq -r --arg asset_prefix "${1}" '.assets[] | select(.name|test($asset_prefix)) | .name' <<< "${latest_release_result}") + asset_url=$(jq -r --arg asset_prefix "${1}" '.assets[] | select(.name|test($asset_prefix)) | .browser_download_url' <<< "${latest_release_result}") + + printf "%b downloading asset ${asset_name}... \n" "${INFO_PREFIX}" + + wget \ + "${asset_url}" \ + -q \ + -O "${1}.zip" + + chmod +x "${1}.zip" + + printf "%b successfully downloaded asset ${asset_name}... \n" "${INFO_PREFIX}" + + exit 0 +} + +# And so, it begins... +main "$1" diff --git a/bin/publish_to_chrome.sh b/bin/publish_to_chrome.sh new file mode 100755 index 00000000..23953050 --- /dev/null +++ b/bin/publish_to_chrome.sh @@ -0,0 +1,118 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$(dirname "${0}") + +source "${SCRIPT_DIR}/set_vars.sh" + +# Public: Gets an access token and uploads & publishes the package to the Chrome Web Store API. +# +# Required environment variables: +# * $CHROME_WEB_STORE_API_CLIENT_ID - a client ID for the Chrome Web Store API. +# * CHROME_WEB_STORE_API_CLIENT_SECRET - a client secret for the Chrome Web Store API. +# * $CHROME_WEB_STORE_API_CLIENT_ID - a refresh token to get an access token for the Chrome Web Store API. +# +# $1 - Chrome item ID. +# $2 - path to zip build. +# +# Examples +# +# ./bin/publish_to_chrome.sh "/path/to/file.zip" +# +# Returns exit code 0 if successful, or 1 the zip file does not exist, the item id is missing, or if the required +# environment variables are missing. +function main { + local access_token + local access_token_result + local publish_result + local upload_result + + set_vars + + if [ -z "${1}" ]; then + printf "%b no item id provided, use: ./bin/publish_to_chrome.sh [item_id] [path_to_zip] \n" "${ERROR_PREFIX}" + exit 1 + fi + + if [ -z "${2}" ]; then + printf "%b no zip path specified, use: ./bin/publish_to_chrome.sh [item_id] [path_to_zip] \n" "${ERROR_PREFIX}" + exit 1 + fi + + if [ ! -f "${2}" ]; then + printf "%b zip file not found at ${1} \n" "${ERROR_PREFIX}" + exit 1 + fi + + if [ -z "${CHROME_WEB_STORE_API_CLIENT_ID}" ]; then + printf "%b client id not provided \n" "${ERROR_PREFIX}" + exit 1 + fi + + if [ -z "${CHROME_WEB_STORE_API_CLIENT_SECRET}" ]; then + printf "%b client secret not provided \n" "${ERROR_PREFIX}" + exit 1 + fi + + if [ -z "${CHROME_WEB_STORE_API_REFRESH_TOKEN}" ]; then + printf "%b refresh token not provided \n" "${ERROR_PREFIX}" + exit 1 + fi + + printf "%b getting access token... \n" "${INFO_PREFIX}" + + access_token_result=$(curl \ + -X POST \ + -s \ + "https://www.googleapis.com/oauth2/v4/token" \ + -d "client_id=${CHROME_WEB_STORE_API_CLIENT_ID}&client_secret=${CHROME_WEB_STORE_API_CLIENT_SECRET}&refresh_token=${CHROME_WEB_STORE_API_REFRESH_TOKEN}&grant_type=refresh_token") + + # check for errors + if [ $(jq 'has("error")' <<< "${access_token_result}") == true ]; then + printf "%b failed to get access token: $(jq '.error_description' <<< "${access_token_result}") \n" "${ERROR_PREFIX}" + exit 1 + fi + + access_token=$(jq '.access_token' <<< "${access_token_result}") + + printf "%b uploading new package... \n" "${INFO_PREFIX}" + + upload_result=$(curl \ + -H "Authorization: Bearer ${access_token}" \ + -H "x-goog-api-version: 2" \ + -X PUT \ + -s \ + -T "${2}" \ + -v \ + "https://www.googleapis.com/upload/chromewebstore/v1.1/items/${1}") + + # check for errors + if [ $(jq 'has("error")' <<< "${upload_result}") == true ]; then + printf "%b failed to upload new package: $(jq '.error.status' <<< "${upload_result}") \n" "${ERROR_PREFIX}" + exit 1 + fi + + printf "%b successfully uploaded package: ${2} \n" "${INFO_PREFIX}" + + printf "%b publishing package... \n" "${INFO_PREFIX}" + + publish_result=$(curl \ + -H "Authorization: Bearer ${access_token}" \ + -H "x-goog-api-version: 2" \ + -H "Content-Length: 0" \ + -X POST \ + -v \ + "https://www.googleapis.com/chromewebstore/v1.1/items/${1}/publish") + + # check for errors + if [ $(jq 'has("error")' <<< "${publish_result}") == true ]; then + printf "%b failed to publish package: $(jq '.error.status' <<< "${publish_result}") \n" "${ERROR_PREFIX}" + exit 1 + fi + + printf "%b successfully published package: ${2} \n" "${INFO_PREFIX}" + + exit 0 +} + +# And so, it begins... +main "$1" "$2" diff --git a/bin/update_issue_templates.sh b/bin/update_issue_templates.sh index 52a5e18c..b3480c92 100755 --- a/bin/update_issue_templates.sh +++ b/bin/update_issue_templates.sh @@ -29,7 +29,7 @@ function main { exit 1 fi -# printf "%b adding version '%s' to .github/ISSUE_TEMPLATE/bug_report_template.yml \n" "${INFO_PREFIX}" "${1}" + printf "%b adding version '%s' to .github/ISSUE_TEMPLATE/bug_report_template.yml \n" "${INFO_PREFIX}" "${1}" version_included=$(version="${1}" yq '(.body[] | select(.id == "version") | .attributes.options) | contains([env(version)])' "${PWD}/.github/ISSUE_TEMPLATE/bug_report_template.yml") if ! "${version_included}"; then