Release-Development #58
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release-Development | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| compiler: | |
| type: choice | |
| description: What compiler to use? | |
| required: true | |
| default: YYC | |
| options: | |
| - YYC | |
| - VM | |
| schedule: | |
| - cron: "0 22 * * *" # every day at 22:00 UTC | |
| jobs: | |
| build_needed: | |
| name: Build needed? | |
| runs-on: ubuntu-latest | |
| env: | |
| COMPILER: ${{ github.event.inputs.compiler || 'YYC' }} | |
| outputs: | |
| needed: ${{ steps.commit_check.outputs.needed }} # Output for skipping | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| lfs: true | |
| - name: Check commit range | |
| id: commit_check | |
| run: | | |
| # default to no build | |
| echo "needed=false" >> $GITHUB_OUTPUT | |
| # manual override | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "Manually triggered → build." | |
| echo "needed=true" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| # determine commit range since last tag | |
| # Use 2>/dev/null to suppress error if no tags exist | |
| LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| if [ -n "$LAST_TAG" ]; then | |
| RANGE="$LAST_TAG..HEAD" | |
| echo "Checking commits in range: $RANGE (since last tag '$LAST_TAG')" | |
| else | |
| RANGE="HEAD" # If no tags, check all commits up to HEAD | |
| echo "No previous tags found. Checking all commits up to HEAD." | |
| fi | |
| # Check if there are *any* commits in the range. | |
| # git log -n 1 --format=%H will return the latest commit SHA if there's at least one. | |
| # If the range is empty (HEAD is same as LAST_TAG), it returns nothing. | |
| COMMITS_IN_RANGE=$(git log $RANGE -n 1 --format=%H 2>/dev/null || echo "") | |
| if [ -z "$COMMITS_IN_RANGE" ]; then | |
| echo "No new commits found in the range '$RANGE'. HEAD is likely the same as the last tag ($LAST_TAG)." | |
| echo "Skipping build as no changes since the last tagged build." | |
| # needed is already defaulted to false, so we just exit. | |
| exit 0 | |
| fi | |
| # If we reached here, there are new commits in the range. | |
| echo "New commits found in range '$RANGE'. Checking their messages." | |
| # collect all commit messages in range | |
| ALL_MSGS=$(git log $RANGE --pretty=%s) | |
| echo "Messages in range:" | |
| # Use sed to indent messages for clarity in logs | |
| echo "$ALL_MSGS" | sed 's/^/ /' | |
| # only build if at least one message does NOT match exclude pattern | |
| # The -v option inverts the match; -E enables extended regex; -q suppresses output. | |
| # The overall command exits successfully (0) if a non-matching line is found. | |
| EXCLUDE="^(docs|chore|style|ci)" | |
| if echo "$ALL_MSGS" | grep -vEq "$EXCLUDE"; then | |
| echo "Found at least one commit message not matching the exclude pattern '$EXCLUDE'." | |
| echo "Build needed." | |
| echo "needed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "All new commit messages match the exclude pattern '$EXCLUDE'." | |
| echo "Skipping build." | |
| # needed is already defaulted to false. | |
| fi | |
| prepare_release: | |
| name: Prepare the tags | |
| runs-on: ubuntu-latest | |
| needs: build_needed | |
| if: needs.build_needed.outputs.needed == 'true' | |
| outputs: | |
| tag_name: ${{ steps.tag_info.outputs.tag_name }} | |
| build_date: ${{ steps.tag_info.outputs.build_date }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set tag name | |
| id: tag_info | |
| run: | | |
| BRANCH_SUFFIX="${GITHUB_REF_NAME##*/}" | |
| DATE_TAG=$(date -u +"%Y-%m-%d-%H%M") | |
| TAG_NAME="$BRANCH_SUFFIX/$DATE_TAG" | |
| echo "Resolved DATE_TAG=$DATE_TAG" | |
| echo "Resolved BRANCH_SUFFIX=$BRANCH_SUFFIX" | |
| echo "Resolved TAG_NAME=$TAG_NAME" | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| echo "build_date=$DATE_TAG" >> $GITHUB_OUTPUT | |
| - name: Cleanup old releases | |
| run: | | |
| set -euo pipefail # Exit immediately if a command exits with a non-zero status | |
| # tag_name looks like: branch-name/date (e.g., main/2025-05-10-2220) | |
| TAG_NAME="${{ steps.tag_info.outputs.tag_name }}" | |
| # Extract the branch prefix from the tag name (e.g., "main/") | |
| # This assumes your tag format is always 'branch-name/date' | |
| BRANCH_PREFIX="${TAG_NAME%%/*}/" | |
| echo "Starting cleanup for releases with prefix: ${BRANCH_PREFIX}" | |
| # --- Added Step: List all tag names found before filtering --- | |
| echo "--- All tag names found by 'gh release list --json tagName': ---" | |
| # Get all tag names first | |
| ALL_TAG_NAMES=$(gh release list --limit 100 --json tagName | jq -r '.[].tagName' || true) | |
| if [ -z "$ALL_TAG_NAMES" ]; then | |
| echo "No releases found at all." | |
| else | |
| echo "$ALL_TAG_NAMES" | cat -n # List all found tags with line numbers | |
| fi | |
| echo "-----------------------------------------------------------" | |
| # Get tag names starting with the prefix, sort reverse chronologically by tag name. | |
| # We use the previously fetched ALL_TAG_NAMES to avoid calling gh release list again | |
| # Use || true at the end of the pipe to prevent the step from failing if no releases match the prefix | |
| TAGS_TO_PROCESS=$(echo "$ALL_TAG_NAMES" | grep "^${BRANCH_PREFIX}" | sort -r || true) | |
| if [ -z "$TAGS_TO_PROCESS" ]; then | |
| echo "No releases found matching prefix '${BRANCH_PREFIX}'. No cleanup needed." | |
| exit 0 | |
| fi | |
| # --- The rest of the logic (count, keep, delete) remains the same --- | |
| # Count the filtered tags | |
| NUM_MATCHING=$(echo "$TAGS_TO_PROCESS" | wc -l) | |
| RELEASES_TO_KEEP=10 # How many releases per branch prefix to keep | |
| echo "Found ${NUM_MATCHING} releases matching prefix '${BRANCH_PREFIX}'. Will keep the latest $RELEASES_TO_KEEP." | |
| COUNT=0 | |
| IFS=$'\n' # Set IFS to newline to correctly iterate over tags | |
| for TAG in $TAGS_TO_PROCESS; do | |
| COUNT=$((COUNT + 1)) | |
| if [ $COUNT -gt $RELEASES_TO_KEEP ]; then | |
| echo "Deleting old release+tag: $TAG" | |
| gh release delete "$TAG" -y --cleanup-tag || echo "Warning: Failed to delete release $TAG. It may have been deleted already." | |
| else | |
| echo "Keeping release+tag: $TAG (it's within the latest $RELEASES_TO_KEEP)" | |
| fi | |
| done | |
| unset IFS # Reset IFS | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needs permissions to delete releases/tags | |
| gamemaker_build: | |
| name: Build | |
| uses: ./.github/workflows/gamemaker_build.yml | |
| secrets: inherit | |
| needs: [prepare_release, build_needed] | |
| if: needs.build_needed.outputs.needed == 'true' | |
| with: | |
| yyc: ${{ (github.event.inputs.compiler || 'YYC') == 'YYC' }} | |
| build_date: ${{ needs.prepare_release.outputs.build_date }} | |
| release: | |
| name: Release | |
| runs-on: ubuntu-latest | |
| needs: [prepare_release, gamemaker_build] | |
| if: needs.build_needed.outputs.needed == 'true' | |
| permissions: | |
| contents: write # Needed for softprops/action-gh-release | |
| steps: | |
| - name: Download built file artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: built-file | |
| path: ./build_output | |
| - name: List downloaded files # Debug step | |
| run: ls -R ./build_output | |
| - name: Prepare Release Name | |
| id: prep_release_name | |
| run: | | |
| rawTagName="${{ needs.prepare_release.outputs.tag_name }}" | |
| # Use Bash parameter expansion: ${parameter//pattern/string} | |
| # Replaces all occurrences of '/' with '-' | |
| formattedTagName="${rawTagName//\//-}" | |
| releaseName="ChapterMaster $formattedTagName" | |
| echo "Calculated release name: $releaseName" | |
| # Set the output using standard Bash redirection to the GITHUB_OUTPUT file | |
| echo "release_name=$releaseName" >> $GITHUB_OUTPUT | |
| - id: create_release | |
| name: Create a release and upload the build | |
| uses: softprops/action-gh-release@v2.3.2 | |
| with: | |
| name: ${{ steps.prep_release_name.outputs.release_name }} | |
| token: ${{ secrets.RELEASE_TOKEN_SECRET }} | |
| tag_name: ${{ needs.prepare_release.outputs.tag_name }} | |
| prerelease: true | |
| generate_release_notes: true | |
| make_latest: false | |
| files: | | |
| ./build_output/${{ needs.gamemaker_build.outputs.built_file }}/* |