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

NEW Create action #1

Merged
merged 13 commits into from
Jun 13, 2022
12 changes: 12 additions & 0 deletions .github/workflows/auto-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Auto-tag
on:
push:
tags:
- '*.*.*'
jobs:
auto-tag:
name: Auto-tag
runs-on: ubuntu-latest
steps:
- name: Auto-tag
uses: silverstripe/gha-auto-tag@main
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
# gha-tag-release
# GitHub Actions - Tag release

Create a tag and an optional release

GuySartorelli marked this conversation as resolved.
Show resolved Hide resolved
## Usage

**workflow.yml**
```yml
steps:
- name: Create tag and release
uses: silverstripe/gha-pull-request@main
with:
tag: 1.2.3
release: true
```

Read more information about the inputs available for [silverstripe/gha-pull-request](https://github.com/silverstripe/gha-pull-request).

## Why there is no SHA input paramater

Creating a tag for a particular SHA, either via the GitHub API or via CLI (i.e. git tag) in an action is strangely blocked. The error is "Resource not accessible by integration" which is a permissions error.

However, tags can be created with the following methods:
- Using `${{ github.sha }}` which is the latest sha in a context instead of historic sha
- Creating a release via GitHub API, which will also create a tag. While it's tempting to just use this and then delete the release, it's seems possible that this may stop working in the future

The following methods have been attempted:
- Using third party actions to create tags
- Passing in `permissions: write-all` from the calling workflow
- Passing in a github token from the calling workflow

It's likely that `${{ github.sha }}` will be good enough though - the intention is that this action will be used to tag the _most recent commit_ on a given branch, e.g. after a pull request is merged.
169 changes: 169 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
name: Tag and release
description: GitHub Action to create a tag and an optional release

inputs:
# Note: there is an explicit reason why there is no sha input parameter - see the readme
tag:
type: string
required: true
delete_existing:
type: boolean
required: false
default: false
release:
type: boolean
required: false
default: false
release_description:
type: string
required: false
default: ''

runs:
using: composite
steps:

GuySartorelli marked this conversation as resolved.
Show resolved Hide resolved
- name: Validate inputs
shell: bash
env:
TAG: ${{ inputs.tag }}
run: |
git check-ref-format "tags/$TAG" > /dev/null
if [[ $? != "0" ]]; then
echo "Invalid tag"
GuySartorelli marked this conversation as resolved.
Show resolved Hide resolved
exit 1
fi

- name: Delete existing release if one exists
if: ${{ inputs.release == 'true' && inputs.delete_existing == 'true' }}
shell: bash
env:
TAG: ${{ inputs.tag }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
# Get id for an existing release matching $TAG
# https://docs.github.com/en/rest/releases/releases#get-a-release-by-tag-name
RESP_CODE=$(curl -w %{http_code} -s -o __response.json \
-X GET https://api.github.com/repos/$GITHUB_REPOSITORY/releases/tags/$TAG \
-H "Accept: application/vnd.github.v3+json")
if [[ $RESP_CODE != "200" ]];
echo "Unable to check tag status for $TAG - HTTP response code was $RESP_CODE"
exit 1
fi
RELEASE_ID=$https://docs.github.com/en/rest/git/refs#get-a-reference(jq .id __response.json)
if [[ $RELEASE_ID == "null" ]]; then
echo "Did not find an existing release for tag $TAG"
else
# https://docs.github.com/en/rest/releases/releases#delete-a-release
RESP_CODE=$(curl -w %{http_code} -s -o /dev/null \
-X DELETE https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$RELEASE_ID \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ github.token }}"
GuySartorelli marked this conversation as resolved.
Show resolved Hide resolved
if [[ $RESP_CODE != "204" ]];
echo "Unable to delete release $RELEASE_ID for tag $TAG - HTTP response code was $RESP_CODE"
exit 1
fi
echo "Deleted existing release $RELEASE_ID for tag $TAG"
fi

- name: Delete existing tag if one exists
if: ${{ inputs.delete_existing == 'true' }}
shell: bash
env:
TAG: ${{ inputs.tag }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
# Check if tag currently exists
# Note: not using https://api.github.com/repos/$GITHUB_REPOSITORY/git/refs/tags/<tag>
# because that uses a "starts-with" filter, so it will also match -beta1 and -rc1 tags
# https://docs.github.com/en/rest/git/refs#get-a-reference
RESP_CODE=$(curl -w %{http_code} -s -o __response.json \
-X GET https://api.github.com/repos/$GITHUB_REPOSITORY/git/refs/tags \
-H "Accept: application/vnd.github.v3+json")
if [[ $RESP_CODE != "200" ]];
echo "Unable to check tag status - HTTP response code was $RESP_CODE"
exit 1
fi
FOUND="true"
# Check there are any tags so we can use jq array selector later
if [[ $(jq 'map(type)' __response.json) =~ object ]]; then
if [[ $(jq '.[] | select(.ref == "refs/tags/$TAG")' __response.json) == "" ]]; then
FOUND="false"
fi
fi
if [[ $FOUND == "false" ]]; then
echo "Did not find an existing tag for $TAG"
else
# Delete tag via GitHub API
# https://docs.github.com/en/rest/reference/git#delete-a-reference
GuySartorelli marked this conversation as resolved.
Show resolved Hide resolved
RESP_CODE=$(curl -w %{http_code} -s -o /dev/null \
curl -s \
-X DELETE https://api.github.com/repos/$GITHUB_REPOSITORY/git/refs/tags/$TAG \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ github.token }}")
if [[ $RESP_CODE != "204" ]];
echo "Unable to delete existing TAG $TAG - HTTP response code was $RESP_CODE"
exit 1
fi
echo "Deleted existing tag $TAG"
fi

- name: Create tag
# Creating a release will also create a tag, so only create explicitly create tag if not creating release
if: ${{ inputs.release == 'false' }}
shell: bash
env:
TAG: ${{ inputs.tag }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
# Create new tag via GitHub API
# https://docs.github.com/en/rest/reference/git#create-a-reference
RESP_CODE=$(curl -w %{http_code} -s -o /dev/null \
-X POST https://api.github.com/repos/$GITHUB_REPOSITORY/git/refs \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ github.token }}" \
-d @- << EOF
{
"sha": "${{ github.sha }}",
"ref": "refs/tags/$TAG"
}
EOF
)
if [[ $RESP_CODE != "201" ]];
echo "Unable to create tag $TAG for sha ${{ github.sha }} - HTTP response code was $RESP_CODE"
exit 1
fi
echo "New tag $TAG created for sha ${{ github.sha }}"
GuySartorelli marked this conversation as resolved.
Show resolved Hide resolved

- name: Create release
if: ${{ inputs.release == 'true' }}
shell: bash
env:
TAG: ${{ inputs.tag }}
RELEASE_DESCRIPTION: ${{ inputs.release_description }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
# Create new release via GitHub API
# https://docs.github.com/en/rest/releases/releases#create-a-release
# Escape double quotes '"' => '\"'
RELEASE_DESCRIPTION=${RELEASE_DESCRIPTION//\"/\\\"}
RESP_CODE=$(curl -w %{http_code} -s -o /dev/null \
-X POST https://api.github.com/repos/$GITHUB_REPOSITORY/releases \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ github.token }}" \
-d @- << EOF
{
"tag_name": "$TAG",
"target_commitish": "${{ github.sha }}",
"name": "$TAG",
"body": "$RELEASE_DESCRIPTION",
"draft": false,
"prerelease": false
}
EOF
)
if [[ $RESP_CODE != "201" ]];
echo "Unable to create release for tag $TAG - HTTP response code was $RESP_CODE"
exit 1
fi
echo "New release $TAG created"