diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cbbef61..4a6913e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,17 @@ on: push: tags: - 'v*' + workflow_dispatch: + inputs: + tag: + description: 'Existing release tag to update (e.g. v1.2.3)' + required: true + type: string + remove_old_assets: + description: 'Remove existing assets before uploading new ones' + required: false + default: true + type: boolean jobs: build-android: @@ -35,6 +46,38 @@ jobs: - name: Generate Freezed Classes run: flutter pub run build_runner build --delete-conflicting-outputs + - name: Determine Release Tag and Version + id: meta + shell: bash + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + RELEASE_TAG="${{ inputs.tag }}" + else + RELEASE_TAG="${{ github.ref_name }}" + fi + echo "RELEASE_TAG=$RELEASE_TAG" >> $GITHUB_ENV + # Derive VERSION_NAME (strip leading v) + VERSION_NAME="${RELEASE_TAG#v}" + echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV + + # Extract current build number from pubspec.yaml if present, otherwise 1 + CURRENT_VERSION_LINE=$(grep "^version:" pubspec.yaml || true) + CURRENT_BUILD=$(echo "$CURRENT_VERSION_LINE" | awk -F'+' '{print $2}') + if [[ -z "$CURRENT_BUILD" ]]; then CURRENT_BUILD=1; fi + + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + # Rebuild mode: compute a unique, monotonic build number without committing + # Use CI run number offset to avoid conflicts across multiple rebuilds + BASE_BUILD=$CURRENT_BUILD + RUN_NUM=${GITHUB_RUN_NUMBER:-1} + BUILD_NUMBER=$((BASE_BUILD + RUN_NUM)) + else + # Tag build: honor the build number committed in pubspec, default to CURRENT_BUILD + BUILD_NUMBER="$CURRENT_BUILD" + fi + echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV + echo "Using tag=$RELEASE_TAG version=$VERSION_NAME build=$BUILD_NUMBER" + #5 Setup Keystore - name: Create Keystore run: | @@ -46,10 +89,10 @@ jobs: working-directory: android - name: Build APK - run: flutter build apk --release + run: flutter build apk --release --build-name "$VERSION_NAME" --build-number "$BUILD_NUMBER" - name: Build appBundle - run: flutter build appbundle --release + run: flutter build appbundle --release --build-name "$VERSION_NAME" --build-number "$BUILD_NUMBER" - name: Upload Artifacts uses: actions/upload-artifact@v4 @@ -79,12 +122,27 @@ jobs: echo "RELEASE_NOTES<> $GITHUB_OUTPUT cat release_notes.md >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT + if: github.event_name == 'push' - - name: Create Release + - name: Create or Update Release (tag push) + if: github.event_name == 'push' uses: ncipollo/release-action@v1 with: artifacts: "build/app/outputs/flutter-apk/app-release.apk,build/app/outputs/bundle/release/app-release.aab" - tag: ${{ github.ref_name }} + tag: ${{ env.RELEASE_TAG }} token: ${{ secrets.GITHUB_TOKEN }} body: ${{ steps.release_notes.outputs.RELEASE_NOTES }} generateReleaseNotes: true + allowUpdates: true + + - name: Update Existing Release (manual rebuild) + if: github.event_name == 'workflow_dispatch' + uses: ncipollo/release-action@v1 + with: + artifacts: "build/app/outputs/flutter-apk/app-release.apk,build/app/outputs/bundle/release/app-release.aab" + tag: ${{ env.RELEASE_TAG }} + token: ${{ secrets.GITHUB_TOKEN }} + allowUpdates: true + removeArtifacts: ${{ inputs.remove_old_assets }} + makeLatest: true + omitBodyDuringUpdate: true diff --git a/scripts/release.sh b/scripts/release.sh index 46533fb..a8a57e8 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,7 +1,9 @@ #!/bin/bash -# LuCI Mobile Release Script (CI-driven) -# Usage: ./scripts/release.sh [major|minor|patch] +# Conduit Mobile Release Script (CI-driven) +# Usage: +# ./scripts/release.sh [major|minor|patch] +# ./scripts/release.sh rebuild [vX.Y.Z] # Rebuild existing tag, bump build number only, update same release assets set -e @@ -30,6 +32,49 @@ if [ ! -f "pubspec.yaml" ]; then exit 1 fi +ACTION=${1:-patch} + +if [ "$ACTION" = "rebuild" ]; then + # Rebuild path: Update existing release assets without changing the tag/version name + # Optionally accepts a tag argument; defaults to latest tag. + TAG_ARG=$2 + if [ -z "$TAG_ARG" ]; then + TAG_VERSION=$(git describe --tags --abbrev=0) + else + TAG_VERSION=$TAG_ARG + fi + + if [ -z "$TAG_VERSION" ]; then + print_error "No tag found. Provide an explicit tag: ./scripts/release.sh rebuild vX.Y.Z" + exit 1 + fi + + print_status "Rebuilding existing release for tag: $TAG_VERSION" + echo + read -p "Proceed to rebuild $TAG_VERSION and update its assets? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_warning "Rebuild cancelled" + exit 0 + fi + + if command -v gh >/dev/null 2>&1; then + print_status "Dispatching GitHub Actions workflow (Release) via gh CLI..." + gh workflow run "Release" \ + --ref main \ + -f tag="$TAG_VERSION" \ + -f remove_old_assets=true + print_status "Workflow dispatched. Track progress in GitHub Actions." + else + print_warning "GitHub CLI (gh) not found. Trigger the workflow manually:" + echo "- Go to: https://github.com/$(git config --get remote.origin.url | sed -E 's#(git@|https://)([^/:]+)[:/]([^/.]+/[^.]+)(\.git)?#\2/\3#')/actions/workflows/release.yml" + echo "- Click 'Run workflow', set tag to $TAG_VERSION, and run." + fi + exit 0 +fi + +# Standard release path (major/minor/patch) + # Check if git is clean if [ -n "$(git status --porcelain)" ]; then print_error "Working directory is not clean. Please commit or stash your changes first." @@ -47,7 +92,7 @@ MINOR=${VERSION_PARTS[1]} PATCH=${VERSION_PARTS[2]} # Determine release type -RELEASE_TYPE=${1:-patch} +RELEASE_TYPE=$ACTION case $RELEASE_TYPE in major) @@ -66,7 +111,7 @@ case $RELEASE_TYPE in NEW_PATCH=$((PATCH + 1)) ;; *) - print_error "Invalid release type. Use: major, minor, or patch" + print_error "Invalid command. Use: major | minor | patch | rebuild [vX.Y.Z]" exit 1 ;; esac @@ -109,4 +154,4 @@ print_status "Creating tag $TAG_VERSION..." git tag -a "$TAG_VERSION" -m "Release $TAG_VERSION" git push origin "$TAG_VERSION" -print_status "Release $TAG_VERSION created and pushed! CI will handle the build and GitHub release." \ No newline at end of file +print_status "Release $TAG_VERSION created and pushed! CI will handle the build and GitHub release."