Skip to content
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
95 changes: 95 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Release

on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
dry_run:
description: "Dry run (build but skip release)"
type: boolean
default: true

permissions:
attestations: write
contents: write
id-token: write

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
build-and-release:
name: Build and Release
runs-on: sprinters:aws:ubuntu-24.04-arm:c7gd.xlarge
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq rsync 7zip

- name: Build all platforms
run: make all
env:
CI_RELEASE: ${{ startsWith(github.ref, 'refs/tags/') }}

- name: Verify build artifacts
run: |
if ! ls releases/*.zip 1>/dev/null 2>&1; then
echo "Error: No release artifacts found in releases/"
exit 1
fi
echo "Found artifacts:"
ls -la releases/*.zip

- name: Generate checksums
run: |
cd releases
sha256sum *.zip > SHA256SUMS
cat SHA256SUMS

- name: Get version
id: version
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
else
echo "version=dev-$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
fi

- name: Attest build provenance
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
uses: actions/attest-build-provenance@v3
with:
subject-path: releases/*.zip

- name: Upload build artifacts
if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
uses: actions/upload-artifact@v4
with:
name: release-${{ steps.version.outputs.version }}
path: releases/*.zip
retention-days: 7

- name: Create GitHub Release
if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') }}
uses: softprops/action-gh-release@v2
with:
name: LessUI ${{ steps.version.outputs.version }}
files: |
releases/*.zip
releases/SHA256SUMS
generate_release_notes: true
make_latest: "true"
52 changes: 43 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,27 @@ endif

###########################################################
# Release versioning
#
# CI builds (GitHub Actions): Use VERSION file (e.g., v0.0.1)
# Local dev builds: Use dev-YYYYMMDD format
#
# Output:
# - ZIP: LessUI-<version>.zip
# - version.txt: <version>\n<git-hash>

BUILD_HASH := $(shell git rev-parse --short HEAD)
export BUILD_HASH
RELEASE_TIME := $(shell TZ=GMT date +%Y%m%d)
RELEASE_BETA =
RELEASE_BASE = LessUI-$(RELEASE_TIME)$(RELEASE_BETA)

# Determine release name based on environment
ifeq ($(CI_RELEASE),true)
# CI release build (tag push): use VERSION file (semver)
RELEASE_VERSION := $(shell cat VERSION 2>/dev/null || echo "v0.0.0")
RELEASE_NAME = LessUI-$(RELEASE_VERSION)
else
# Local dev build: use dev-DATE format with collision detection
RELEASE_BASE = LessUI-dev-$(RELEASE_TIME)
RELEASE_DOT := $(shell find ./releases/. -name "${RELEASE_BASE}-*.zip" 2>/dev/null | wc -l | sed 's/ //g')
# First build has no suffix, subsequent builds use -1, -2, etc.
# Check if unnumbered release exists, if so start numbering from RELEASE_DOT+1
RELEASE_SUFFIX := $(shell \
if [ "$(RELEASE_DOT)" = "0" ] && [ ! -f "./releases/${RELEASE_BASE}.zip" ]; then \
echo ""; \
Expand All @@ -52,6 +64,8 @@ RELEASE_SUFFIX := $(shell \
echo "-$$(($(RELEASE_DOT) + 1))"; \
fi)
RELEASE_NAME = $(RELEASE_BASE)$(RELEASE_SUFFIX)
RELEASE_VERSION = dev-$(RELEASE_TIME)$(RELEASE_SUFFIX)
endif

###########################################################
# Build configuration
Expand All @@ -78,7 +92,7 @@ endif
export OPT_FLAGS
export LOG_FLAGS

.PHONY: help build test coverage lint format dev dev-run dev-run-4x3 dev-run-16x9 dev-clean all shell name clean setup special tidy stage compress package dev-deploy dev-build-deploy
.PHONY: help build test coverage lint format dev dev-run dev-run-4x3 dev-run-16x9 dev-clean all shell name clean setup special tidy stage compress package dev-deploy dev-build-deploy release release-patch release-minor release-major

export MAKEFLAGS=--no-print-directory

Expand Down Expand Up @@ -115,6 +129,11 @@ help:
@echo " make dev-deploy Deploy to SD card (requires LESSUI_DEV volume)"
@echo " make dev-build-deploy Build and deploy (no compression)"
@echo ""
@echo "Release:"
@echo " make release-patch Create patch release (v1.0.0 → v1.0.1)"
@echo " make release-minor Create minor release (v1.0.1 → v1.1.0)"
@echo " make release-major Create major release (v1.1.0 → v2.0.0)"
@echo ""
@echo "Housekeeping:"
@echo " make clean Remove all build artifacts"
@echo " make name Print release name"
Expand All @@ -132,6 +151,21 @@ shell:
name:
@echo $(RELEASE_NAME)

# Create a release using git-flow
# Usage: make release-patch (or release-minor/release-major)
release-patch:
@./scripts/release.sh patch

release-minor:
@./scripts/release.sh minor

release-major:
@./scripts/release.sh major

# Legacy alias (deprecated)
release:
@./scripts/release.sh $(TYPE)

# QA convenience targets (forward to Makefile.qa)
test:
@$(MAKE) -f Makefile.qa test
Expand Down Expand Up @@ -325,7 +359,7 @@ stage: tidy
@echo "# ----------------------------------------------------"
@mkdir -p ./build/PAYLOAD/.system
@rsync -a ./build/SYSTEM/ ./build/PAYLOAD/.system/
@cd ./build/PAYLOAD/.system && printf '%s\n%s\n' "$(RELEASE_NAME)" "$(BUILD_HASH)" > version.txt
@cd ./build/PAYLOAD/.system && printf '%s\n%s\n' "$(RELEASE_VERSION)" "$(BUILD_HASH)" > version.txt
@./commits.sh > ./build/PAYLOAD/.system/commits.txt
@mkdir -p ./build/PAYLOAD/.system/common/cores/arm32 ./build/PAYLOAD/.system/common/cores/arm64
@jq -r '.cores[].core' ./workspace/all/paks/Emus/cores.json | sort -u | while read core; do \
Expand All @@ -350,12 +384,12 @@ compress:
rm -rf ./workspace/readmes; \
fi
@if [ -d ./build/PAYLOAD/.tmp_update ]; then \
cd ./build/PAYLOAD && 7zz a -t7z -mx=9 -md=16m -mmt=on LessUI.7z .system .tmp_update; \
cd ./build/PAYLOAD && 7z a -t7z -mx=9 -md=16m -mmt=on LessUI.7z .system .tmp_update; \
else \
cd ./build/PAYLOAD && 7zz a -t7z -mx=9 -md=16m -mmt=on LessUI.7z .system; \
cd ./build/PAYLOAD && 7z a -t7z -mx=9 -md=16m -mmt=on LessUI.7z .system; \
fi
@mv ./build/PAYLOAD/LessUI.7z ./build/BASE
@cd ./build/BASE && 7zz a -tzip -mmt=on -mx=5 ../../releases/$(RELEASE_NAME).zip Tools Bios Roms Saves bin miyoo miyoo354 trimui rg35xx rg35xxplus miyoo355 magicx miyoo285 em_ui.sh LessUI.7z README.txt
@cd ./build/BASE && 7z a -tzip -mmt=on -mx=5 ../../releases/$(RELEASE_NAME).zip Tools Bios Roms Saves bin miyoo miyoo354 trimui rg35xx rg35xxplus miyoo355 magicx miyoo285 em_ui.sh LessUI.7z README.txt
@echo "$(RELEASE_NAME)" > ./build/latest.txt

# Package: full release build (stage + compress)
Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v0.0.0
161 changes: 161 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#!/bin/bash
set -e

# Usage: ./scripts/release.sh [patch|minor|major]
#
# This script automates the git-flow release process:
# 1. Computes next version from latest tag
# 2. Prompts for confirmation
# 3. Creates git-flow release branch
# 4. Bumps VERSION file
# 5. Finishes release (merges to main and develop)
# 6. Pushes everything including tags
#
# After push, GitHub Actions will build and publish the release.

TYPE="${1:-patch}"

# Check prerequisites
if ! git flow version &>/dev/null; then
echo "Error: git-flow is not installed"
echo "Install with: brew install git-flow-avh"
exit 1
fi

if ! git config --get gitflow.branch.master &>/dev/null; then
echo "Error: git-flow not initialized in this repository"
echo "Run: git flow init"
exit 1
fi

if [[ ! "$TYPE" =~ ^(patch|minor|major)$ ]]; then
echo "Usage: $0 [patch|minor|major]"
echo ""
echo " patch - Bug fixes, minor changes (v1.0.0 → v1.0.1)"
echo " minor - New features, backwards compatible (v1.0.1 → v1.1.0)"
echo " major - Breaking changes (v1.1.0 → v2.0.0)"
exit 1
fi

# Get latest tag
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "Current version: $LATEST_TAG"

# Parse version components
VERSION="${LATEST_TAG#v}"
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"

# Compute next version
case "$TYPE" in
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
patch) PATCH=$((PATCH + 1)) ;;
esac

NEXT_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
echo "Next version: $NEXT_VERSION"
echo ""

# Confirm
read -p "Proceed with release $NEXT_VERSION? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborted."
exit 1
fi

# Ensure we're on develop
CURRENT_BRANCH=$(git branch --show-current)
if [ "$CURRENT_BRANCH" != "develop" ]; then
echo "Error: Must be on develop branch (currently on $CURRENT_BRANCH)"
exit 1
fi

# Ensure develop is up to date with remote
echo "Checking remote sync..."
git fetch origin develop --quiet
LOCAL=$(git rev-parse develop)
REMOTE=$(git rev-parse origin/develop)
if [ "$LOCAL" != "$REMOTE" ]; then
echo "Error: Local develop is not in sync with origin/develop"
echo " Local: $LOCAL"
echo " Remote: $REMOTE"
echo "Please pull or push as needed."
exit 1
fi

# Ensure working directory is clean
if ! git diff-index --quiet HEAD --; then
echo "Error: Working directory has uncommitted changes"
exit 1
fi

# Get the main branch name from git-flow config
MAIN_BRANCH=$(git config --get gitflow.branch.master)
if [ -z "$MAIN_BRANCH" ]; then
echo "Error: Could not determine main branch from git-flow config"
exit 1
fi

# Ensure main branch exists and is in sync with remote
echo "Checking $MAIN_BRANCH branch..."
git fetch origin "$MAIN_BRANCH" --quiet
if ! git rev-parse "$MAIN_BRANCH" &>/dev/null; then
echo "Error: Branch '$MAIN_BRANCH' does not exist locally"
exit 1
fi
MAIN_LOCAL=$(git rev-parse "$MAIN_BRANCH")
MAIN_REMOTE=$(git rev-parse "origin/$MAIN_BRANCH" 2>/dev/null) || true
if [ -n "$MAIN_REMOTE" ] && [ "$MAIN_LOCAL" != "$MAIN_REMOTE" ]; then
echo "Error: Local $MAIN_BRANCH is not in sync with origin/$MAIN_BRANCH"
echo " Local: $MAIN_LOCAL"
echo " Remote: $MAIN_REMOTE"
echo "Please pull or push as needed."
exit 1
fi

# Cleanup function to handle failures after release branch is created
cleanup_release() {
echo ""
echo "Error: Release failed. Cleaning up..."
echo "You may need to manually clean up with:"
echo " git flow release delete $NEXT_VERSION"
echo " git checkout develop"
exit 1
}

# Start release
echo ""
echo "Starting release $NEXT_VERSION..."
git flow release start "$NEXT_VERSION"

# Set trap to handle failures after release branch is created
trap cleanup_release ERR

# Update VERSION file
echo "$NEXT_VERSION" > VERSION
git add VERSION
git commit -m "Bump version to $NEXT_VERSION"

# Finish release (merges to main and develop, creates tag)
# Use GIT_MERGE_AUTOEDIT=no to avoid editor prompts
export GIT_MERGE_AUTOEDIT=no
git flow release finish -m "$NEXT_VERSION" "$NEXT_VERSION"

# Clear trap after successful finish
trap - ERR

# Push everything
echo ""
echo "Pushing to origin..."
git push origin "$MAIN_BRANCH" develop --tags

# Get repository URL from git remote
REPO_URL=$(git remote get-url origin | sed -E 's/.*github.com[:\/](.*)\.git/\1/' | sed 's/\.git$//')

echo ""
echo "Release $NEXT_VERSION complete!"
echo "GitHub Actions will now build and publish the release."
echo ""
echo "Monitor the build at:"
echo " https://github.com/${REPO_URL}/actions"
2 changes: 1 addition & 1 deletion workspace/rg35xxplus/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ early: $(REQUIRES_SDL2) $(REQUIRES_DTC) $(REQUIRES_FBSET)
@mkdir -p other
@cd $(REQUIRES_DTC) && CC=${CROSS_COMPILE}gcc $(MAKE) -s NO_PYTHON=1 dtc
@cd $(REQUIRES_FBSET) && $(MAKE) -s
@cd $(REQUIRES_SDL2) && MAKEFLAGS=--no-print-directory CFLAGS="-O2 -march=armv8-a+crc -mtune=cortex-a53 -mcpu=cortex-a53 -ffast-math -ftree-vectorize" \
@cd $(REQUIRES_SDL2) && MAKEFLAGS=--no-print-directory CFLAGS="-O2 -marm -mtune=cortex-a53 -mcpu=cortex-a53 -ffast-math -ftree-vectorize" \
./configure CC=${CROSS_COMPILE}gcc --host=arm-buildroot-linux-gnueabihf \
--enable-arm-neon \
--disable-oss \
Expand Down
2 changes: 1 addition & 1 deletion workspace/rg35xxplus/init/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ TARGET = init
PRODUCT = $(TARGET).elf

CC = $(CROSS_COMPILE)gcc
CFLAGS = -march=armv8-a -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53
CFLAGS = -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53
CFLAGS += -Wall -Wextra -Wsign-compare -Wshadow -Wnull-dereference -Wundef \
-Wno-unused-variable -Wno-unused-function -Wno-unused-parameter \
-Wno-cast-align -Wno-missing-field-initializers -Wno-format -Werror
Expand Down
2 changes: 1 addition & 1 deletion workspace/rg35xxplus/platform/Makefile.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# rg35xx
ARCH = -march=armv8-a -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53
ARCH = -marm -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53
LIBS = -flto
SDL = SDL2