Skip to content

Commit

Permalink
Rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthri committed Nov 18, 2024
1 parent 96bd83f commit e180a9b
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 258 deletions.
109 changes: 109 additions & 0 deletions .github/workflows/i.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Synchronize Pointag

on:
workflow_call:

defaults:
run:
shell: bash

jobs:
synchronize-pointag:
runs-on: ubuntu-22.04
if: ${{ (github.event_name != 'push' || startsWith(github.event.ref, 'refs/tags/')) && (github.event_name != 'delete' || github.event.ref_type == 'tag') }}
env:
CONTINUE_JOB: 1
permissions:
contents: write
timeout-minutes: 2

steps:
- name: Extract information
id: extract
env:
EVENT_REF: ${{ github.event.ref }}
IS_PUSH_EVENT: ${{ github.event_name == 'push' }}
IS_MISC_EVENT: ${{ github.event_name != 'push' && github.event_name != 'delete' }}
run: |
if [[ $IS_MISC_EVENT == 'true' ]] ; then
echo '::error::The workflow only supports the on.push and the on.delete triggers.'
exit 1
fi
if [[ $IS_PUSH_EVENT == 'true' ]] ; then
EVENT_REF="${EVENT_REF#refs/tags/}"
fi
if [[ $EVENT_REF == */* ]] ; then
tag_directory="${EVENT_REF%/*}/"
fi
version="${EVENT_REF##*/}"
if [[ $version =~ ^v[[:digit:]]$ ]] ; then
echo '::notice::Refusing to overwrite user-initiated update of a pointag.'
echo 'CONTINUE_JOB=0' >> "$GITHUB_ENV"
exit 0
elif [[ ! $version =~ ^v[0-9]+\.[0-9] ]] ; then
echo '::error::Incorrect version format.'
exit 1
fi
major_pointag="$tag_directory${version%%.*}"
echo "tag-directory=$tag_directory" >> "$GITHUB_OUTPUT"
echo "major-pointag=$major_pointag" >> "$GITHUB_OUTPUT"
echo "major-version=$version" >> "$GITHUB_OUTPUT"
- name: Update or delete pointag
if: ${{ env.CONTINUE_JOB == '1' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IS_DELETE_EVENT: ${{ github.event_name == 'delete' }}

MAJOR_POINTAG: ${{ steps.extract.outputs.major-pointag }}
MAJOR_VERSION: ${{ steps.extract.outputs.major-version }}
TAG_DIRECTORY: ${{ steps.extract.outputs.tag-directory }}

REPOSITORY_URL: ${{ github.server_url }}/${{ github.repository }}.git
run: |
git -c init.defaultBranch=default-branch init
git remote add origin "$REPOSITORY_URL"
git config "http.$REPOSITORY_URL.extraheader" "Authorization: Basic $(echo -n "x-access-token:$GH_TOKEN" | base64 -w0)"
tags_under_major_version="$(git ls-remote --sort=v:refname --tags origin "refs/tags/$MAJOR_POINTAG*")"
major_pointag_information="$(head -1 <<< "$tags_under_major_version")"
highest_tag_information="$(tail -1 <<< "$tags_under_major_version")"
highest_tag_reference="$(cut -s -f 2 <<< "$highest_tag_information")"
if [[ -z $major_pointag_information ]] ; then
if [[ $IS_DELETE_EVENT == 'true' ]] ; then
echo '::notice::User-initated deletion of major pointag.'
exit 0
else
echo "::error::Failed to find any tags under $MAJOR_VERSION."
exit 1
fi
elif [[ $major_pointag_information == $highest_tag_information ]] ; then
if [[ $highest_tag_reference == "refs/tags/$MAJOR_POINTAG" ]] ; then
echo '::notice::Deleting dangling pointag.'
git push -f origin ":refs/tags/$MAJOR_POINTAG" || true
exit 0
else
create_pointag='true'
fi
fi
highest_tag_revision="$(cut -s -f 1 <<< "$highest_tag_information")"
if [[ $create_pointag != 'true' ]] ; then
major_pointag_revision="$(cut -s -f 1 <<< "$major_pointag_information")"
if [[ $major_pointag_revision == $highest_tag_revision ]] ; then
echo "$MAJOR_POINTAG is already pointing at the highest tag under it."
exit 0
fi
echo "Setting $MAJOR_POINTAG to $highest_tag_revision ($highest_tag_reference)."
else
echo "Creating $MAJOR_POINTAG and setting it to $highest_tag_revision ($highest_tag_reference)."
fi
git fetch --depth 1 origin "$highest_tag_revision"
git push -f origin "FETCH_HEAD:refs/tags/$MAJOR_POINTAG"
14 changes: 14 additions & 0 deletions .github/workflows/run-synchronize-pointag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Synchronize Pointag

on:
delete:

push:
tags:
- '**'

jobs:
synchronize-pointag:
permissions:
contents: write
uses: ./.github/workflows/i.yml
16 changes: 0 additions & 16 deletions .github/workflows/run-update-major-tag.yml

This file was deleted.

121 changes: 0 additions & 121 deletions .github/workflows/update-major-tag.yml

This file was deleted.

37 changes: 26 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# update-major-tag
A reusable workflow which automatically updates the major tag(for example, `v1`, `Test.App/v2`) when a new tag is created.
# synchronize-pointag
A reusable workflow which automatically creates and synchronizes pointer tags ("pointags") when tags are created, updated, or deleted.

## Installation
Add a new workflow under `.github/workflows/` with the following contents.
Add a new workflow under `.github/workflows/` with the following contents,
```yml
name: Update v<Major> Tag
run-name: |
Update major tag: ${{ github.event_name }}${{ github.event_name == 'push' && (github.event.created && ' created' || ' deleted') || '' }} ${{ github.event.ref }}
name: Synchronize Pointag

on:
delete:
Expand All @@ -16,13 +14,30 @@ on:
- '**'

jobs:
update-tag:
synchronize-pointag:
permissions:
contents: write
uses: Arthri/update-major-tag/.github/workflows/update-major-tag.yml@v1

uses: Arthri/synchronize-pointag/.github/workflows/i.yml@v2
```
> [!NOTE]
> `on.push` is used over `on.create` primarily for two reasons:
> 1. `on.create` is noisier because it does not support filtering by tags or branches, and consequently, always triggers when new branches are pushed.
> 1. `on.create` is not triggered by tag updates.
>
> Furthermore, `on.delete` is used because `on.push` is not triggered by tag deletions. Unfortunately, it does not support filtering similar to `on.create` and triggers even when branches are deleted.

## Usage
1. Create a new tag. For example, `v1.4.2`, `Test.App/v2.5.3`.
1. Expect the workflow to run and create a tag such as `v1` or `Test.App/v1` in a few moments.
1. Create and push a new tag. For example, `v1.4.2`, `Test.App/v2.5.3`.
1. Expect the workflow to run and create a tag such as `v1` or `Test.App/v2` in a few moments.

A list of tags and their corresponding pointags are provided for reference below.
- `v1.12.0` → `v1`
- `v1.56.8` → `v1`
- `v2.11` → `v2`
- `TagDirectory/v3.4.0` → `TagDirectory/v3`
- `Tag/With/Path/v3.11.0` → `Tag/With/Path/v3`
- `Tag/With/Path/v3.56` → `Tag/With/Path/v3`

> [!WARNING]
> Although discouraged, pointags may be manually updated. The workflow will detect the update but will terminate and do nothing.
Loading

0 comments on commit e180a9b

Please sign in to comment.