Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitHub Actions Support #77

Merged
merged 4 commits into from
Oct 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Copied from https://github.com/firebase/extensions/blob/next/.github/workflows/release.yml

name: Release

on:
push:
branches:
- master

jobs:
release:
name: "Create Releases"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Release Script
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
./.github/workflows/scripts/release.sh
202 changes: 202 additions & 0 deletions .github/workflows/scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Copied and modified from https://github.com/firebase/extensions/blob/next/.github/workflows/scripts/release.sh. Changes:
# 1. Read the extension name from the extension.yaml file instead of from the directory name.

#!/bin/bash
set -e
set -o pipefail

# Uncomment for testing purposes:

#GITHUB_TOKEN=YOUR_TOKEN_HERE
#GITHUB_REPOSITORY=invertase/extensions-release-testing

# -------------------
# Functions
# -------------------
json_escape() {
printf '%s' "$1" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))'
}

# Creates a new GitHub release
# ARGS:
# 1: Name of the release (becomes the release title on GitHub)
# 2: Markdown body of the release
# 3: Release Git tag
create_github_release() {
local response=''
local release_name=$1
local release_body=$2
local release_tag=$3

local body='{
"tag_name": "%s",
"target_commitish": "master",
"name": "%s",
"body": %s,
"draft": false,
"prerelease": false
}'

# shellcheck disable=SC2059
body=$(printf "$body" "$release_tag" "$release_name" "$release_body")
response=$(curl --request POST \
--url https://api.github.com/repos/${GITHUB_REPOSITORY}/releases \
--header "Authorization: Bearer $GITHUB_TOKEN" \
--header 'Content-Type: application/json' \
--data "$body" \
-s)

created=$(echo "$response" | python -c "import sys, json; data = json.load(sys.stdin); print(data.get('id', sys.stdin))")
if [ "$created" != "$response" ]; then
printf "release created successfully!\n"
else
printf "release failed to create; "
printf "\n%s\n" "$body"
printf "\n%s\n" "$response"
exit 1
fi
}

# Updates an existing GitHub release
# ARGS:
# 1: Name of the release (becomes the release title on GitHub)
# 2: Markdown body of the release
# 3: Release Git tag
# 4: ID of the existing release
update_github_release() {
local response=''
local release_name=$1
local release_body=$2
local release_tag=$3
local release_id=$4

local body='{
"tag_name": "%s",
"target_commitish": "master",
"name": "%s",
"body": %s,
"draft": false,
"prerelease": false
}'

# shellcheck disable=SC2059
body=$(printf "$body" "$release_tag" "$release_name" "$release_body")
response=$(curl --request PATCH \
--url "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$release_id" \
--header "Authorization: Bearer $GITHUB_TOKEN" \
--header 'Content-Type: application/json' \
--data "$body" \
-s)

updated=$(echo "$response" | python -c "import sys, json; data = json.load(sys.stdin); print(data.get('id', sys.stdin))")
if [ "$updated" != "$response" ]; then
printf "release updated successfully!\n"
else
printf "release failed to update; "
printf "\n%s\n" "$body"
printf "\n%s\n" "$response"
exit 1
fi
}

# Creates or updates a GitHub release
# ARGS:
# 1: Extension name
# 2: Extension version
# 3: Markdown body to use for the release
create_or_update_github_release() {
local response=''
local release_id=''
local extension_name=$1
local extension_version=$2
local release_body=$3
local release_tag="$extension_name-v$extension_version"
local release_name="$extension_name v$extension_version"

response=$(curl --request GET \
--url "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/${release_tag}" \
--header "Authorization: Bearer $GITHUB_TOKEN" \
--header 'Content-Type: application/json' \
--data "$body" \
-s)

release_id=$(echo "$response" | python -c "import sys, json; data = json.load(sys.stdin); print(data.get('id', 'Not Found'))")
if [ "$release_id" != "Not Found" ]; then
existing_release_body=$(echo "$response" | python -c "import sys, json; data = json.load(sys.stdin); print(data.get('body', ''))")
existing_release_body=$(json_escape "$existing_release_body")
# Only update it if the release body is different (this can happen if a change log is manually updated)
printf "Existing release (%s) found for %s - " "$release_id" "$release_tag"
if [ "$existing_release_body" != "$release_body" ]; then
printf "updating it with updated release body ... "
update_github_release "$release_name" "$release_body" "$release_tag" "$release_id"
else
printf "skipping it as release body is already up to date.\n"
fi
else
response_message=$(echo "$response" | python -c "import sys, json; data = json.load(sys.stdin); print(data.get('message'))")
if [ "$response_message" != "Not Found" ]; then
echo "Failed to query release '$release_name' -> GitHub API request failed with response: $response_message"
echo "$response"
exit 1
else
printf "Creating new release '%s' ... " "$release_tag"
create_github_release "$release_name" "$release_body" "$release_tag"
fi
fi
}

# -------------------
# Main Script
# -------------------

# Ensure that the GITHUB_TOKEN env variable is defined
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "Missing required GITHUB_TOKEN env variable. Set this on the workflow action or on your local environment."
exit 1
fi

# Ensure that the GITHUB_REPOSITORY env variable is defined
if [[ -z "$GITHUB_REPOSITORY" ]]; then
echo "Missing required GITHUB_REPOSITORY env variable. Set this on the workflow action or on your local environment."
exit 1
fi

# Find all extensions based on whether a extension.yaml file exists in the directory
for i in $(find . -type f -name 'extension.yaml' -exec dirname {} \; | sort -u); do
# Pluck extension latest name from yaml file
extension_name=$(awk '/^name: /' "$i/extension.yaml" | sed "s/name: //")
# Pluck extension latest version from yaml file
extension_version=$(awk '/^version: /' "$i/extension.yaml" | sed "s/version: //")

changelog_contents="No changelog found for this version."

# Ensure changelog exists
if [ -f "$i/CHANGELOG.md" ]; then
# Pluck out change log contents for the latest extension version
changelog_contents=$(awk -v ver="$extension_version" '/^## Version / { if (p) { exit }; if ($3 == ver) { p=1; next} } p && NF' "$i/CHANGELOG.md")
else
echo "WARNING: A changelog could not be found at $i/CHANGELOG.md - a default entry will be used instead."
fi

# JSON escape the markdown content for the release body
changelog_contents=$(json_escape "$changelog_contents")

# Creates a new release if it does not exist
# OR
# Updates an existing release with updated content (allows updating CHANGELOG.md which will update relevant release body)
create_or_update_github_release "$extension_name" "$extension_version" "$changelog_contents"
done
47 changes: 47 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Copied and modified from https://github.com/firebase/extensions/blob/next/.github/workflows/test.yml. Changes:
# 1. Changed node versions list to only 18.
# 2. Updated paths to use functions directory.

name: Testing

on:
push:
branches:
- "**"
pull_request:
branches:
- "**"

jobs:
nodejs:
runs-on: ubuntu-latest
strategy:
matrix:
node: ["18"]
name: node.js_${{ matrix.node }}_test
steps:
- uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: npm install
run: cd functions && npm i
- name: npm test
run: cd functions && npm run test
40 changes: 40 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Copied from https://github.com/firebase/extensions/blob/next/.github/workflows/validate.yml
# 1. Changed node versions list to only 18.
# 2. Updated paths to use functions directory.

name: Validate

on:
pull_request:
branches:
- "**"

jobs:
formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 18
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: npm install
run: cd functions && npm i
- name: Prettier Lint Check
run: cd functions && npm run lint
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Add a configurable retry to allow a higher chance of requests causing transient failures to succeed (PR #69)
- Added linter config and updated packages. (PR #70)
- Node.JS 18 runtime for functions (PR #73)
- GitHub Actions Support to assist with verification and publishing (PR #77)

## Version 0.5.3

Expand Down
Loading