You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ytdl-android/.github/workflows/test-debug-release.yml

242 lines
8.6 KiB
YAML

name: "Test Debug Release"
on:
workflow_dispatch:
inputs:
architecture:
description: 'APK architecture to upload for manual test builds'
required: true
type: choice
options:
- arm64-v8a
- armeabi-v7a
- x86
- x86_64
- universal
default: universal
push:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
build-debug:
name: Build test debug APK
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Set up JDK 21
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
with:
distribution: 'temurin'
java-version: '21'
cache: 'gradle'
verify-signature: true
- name: Read latest dated version from CHANGELOG.md
id: changelog
shell: bash
run: |
set -euo pipefail
if [[ ! -f CHANGELOG.md ]]; then
echo "::error::CHANGELOG.md not found"
exit 1
fi
# Expected format (this repo's changelog uses a blockquoted heading):
# > # 1.8.9.1 (2026-06)
CHANGELOG_LINE="$(
grep -m1 -E '^>[[:space:]]+#[[:space:]]+[^[:space:]]+[[:space:]]+\([0-9]{4}-[0-9]{2}\)[[:space:]]*$' CHANGELOG.md
)" || {
echo "::error::No dated version heading was found in CHANGELOG.md"
echo "::error::Expected: > # 1.8.9.1 (YYYY-MM)"
exit 1
}
VERSION="$(sed -E 's/^>[[:space:]]+#[[:space:]]+([^[:space:]]+).*$/\1/' <<< "$CHANGELOG_LINE")"
RELEASE_DATE="$(sed -E 's/^>[[:space:]]+#[[:space:]]+[^[:space:]]+[[:space:]]+\(([0-9]{4}-[0-9]{2})\).*$/\1/' <<< "$CHANGELOG_LINE")"
# Extract the complete latest dated release section, excluding
# any older releases. Stops at the next top-level version heading.
RELEASE_SECTION="$(
awk -v heading="$CHANGELOG_LINE" '
$0 == heading { found=1; print; next }
found && /^>[[:space:]]+#[[:space:]]+/ { exit }
found { print }
' CHANGELOG.md
)"
# Keep the values safe for filenames/tags.
SAFE_VERSION="$(tr -cd '[:alnum:]._-v' <<< "$VERSION")"
if [[ -z "$SAFE_VERSION" || -z "$RELEASE_DATE" || -z "$RELEASE_SECTION" ]]; then
echo "::error::Could not extract the latest dated release section from CHANGELOG.md"
exit 1
fi
{
echo "version=$SAFE_VERSION"
echo "date=$RELEASE_DATE"
echo "heading=$CHANGELOG_LINE"
echo "section<<CHANGELOG_EOF"
echo "$RELEASE_SECTION"
echo "CHANGELOG_EOF"
} >> "$GITHUB_OUTPUT"
echo "Latest dated changelog version: $SAFE_VERSION ($RELEASE_DATE)"
- name: Generate debug keystore
run: |
if [[ -f app/debug.keystore ]]; then
echo "Using the committed app/debug.keystore — signature stays the same across runs."
else
echo "::warning::app/debug.keystore not found in the repo — generating a temporary one for this run only. Commit the keystore this workflow uploads as a build artifact to app/debug.keystore so future test builds share one signature and can be installed as updates instead of reinstalls."
keytool -genkeypair -v \
-keystore app/debug.keystore \
-storepass android \
-keypass android \
-alias androiddebugkey \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-dname "CN=Android Debug,O=Android,C=US"
fi
# app/build.gradle only defines signingConfigs.debug when this
# file exists and is non-empty — without it, the keystore above
# is never actually referenced and the build silently falls
# back to Gradle's own implicit debug signing config instead.
cat > keystore.properties <<EOF
signingConfig.storeFile=debug.keystore
signingConfig.storePassword=android
signingConfig.keyAlias=androiddebugkey
signingConfig.keyPassword=android
EOF
- name: Create local.properties
run: touch local.properties
- name: Build foss debug APK
run: |
chmod +x ./gradlew
./gradlew assembleFossDebug --stacktrace --no-daemon
- name: Locate and rename APK
id: apk
shell: bash
env:
VERSION: ${{ steps.changelog.outputs.version }}
RELEASE_DATE: ${{ steps.changelog.outputs.date }}
TARGET_ARCH: ${{ github.event_name == 'workflow_dispatch' && inputs.architecture || 'universal' }}
run: |
set -euo pipefail
mkdir -p dist
shopt -s nullglob
SHORT_SHA="${GITHUB_SHA::7}"
# Scoped to the foss flavor only (assembleFossDebug above), so
# this looks directly in that flavor's debug output directory.
APK_PATHS=(app/build/outputs/apk/foss/debug/*.apk)
if (( ${#APK_PATHS[@]} == 0 )); then
echo "::error::No debug APKs were produced"
exit 1
fi
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
echo "dir=dist" >> "$GITHUB_OUTPUT"
SELECTED_APK=""
SELECTED_ABI=""
SELECTED_FLAVOR=""
for APK_PATH in "${APK_PATHS[@]}"; do
# Flavor is the directory two levels above the APK file
# (.../apk/<flavor>/debug/<file>.apk).
FLAVOR="$(basename "$(dirname "$(dirname "$APK_PATH")")")"
# Pull the ABI out of the filename by matching a known ABI
# token instead of assuming the default "app-<abi>-debug"
# naming — this project's APKs are named "YTDLnis-...".
ABI="$(basename "$APK_PATH" .apk | grep -oE 'arm64-v8a|armeabi-v7a|x86_64|x86|universal' || true)"
if [[ -z "$ABI" ]]; then
ABI="$(basename "$APK_PATH" .apk)"
fi
if [[ "$ABI" == "$TARGET_ARCH" ]]; then
SELECTED_APK="$APK_PATH"
SELECTED_ABI="$ABI"
SELECTED_FLAVOR="$FLAVOR"
break
fi
done
if [[ -z "$SELECTED_APK" ]]; then
echo "::error::No APK found for requested architecture: $TARGET_ARCH"
echo "::error::Produced APKs:"
printf ' %s\n' "${APK_PATHS[@]}"
exit 1
fi
OUTPUT_APK="dist/YTDLnis-debug-v${VERSION}-${RELEASE_DATE}-${SHORT_SHA}-${SELECTED_FLAVOR}-${SELECTED_ABI}.apk"
cp "$SELECTED_APK" "$OUTPUT_APK"
echo "architecture=$SELECTED_ABI" >> "$GITHUB_OUTPUT"
echo "apk=$OUTPUT_APK" >> "$GITHUB_OUTPUT"
echo "Selected architecture: $SELECTED_ABI"
echo "Selected APK: $SELECTED_APK"
- name: Create internal debug release notes
id: notes
shell: bash
env:
VERSION: ${{ steps.changelog.outputs.version }}
RELEASE_DATE: ${{ steps.changelog.outputs.date }}
CHANGELOG_HEADING: ${{ steps.changelog.outputs.heading }}
CHANGELOG_SECTION: ${{ steps.changelog.outputs.section }}
SHORT_SHA: ${{ steps.apk.outputs.short_sha }}
ARCHITECTURE: ${{ steps.apk.outputs.architecture }}
run: |
cat > debug-release-notes.md <<EOF
## YTDLnis internal debug build
**Changelog version:** ${VERSION}
**Changelog date:** ${RELEASE_DATE}
**Commit:** ${GITHUB_SHA}
**Short commit:** ${SHORT_SHA}
**Architecture:** ${ARCHITECTURE}
This is an **internal testing build** generated manually from the repository.
- It is a debug build.
- It is a prerelease.
- It does **not** use the production release tag.
- The changelog version/date are used for identification only.
- Install only for internal testing.
### Latest dated CHANGELOG.md entry
${CHANGELOG_SECTION}
EOF
- name: Upload as workflow artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: YTDLnis-debug-foss-v${{ steps.changelog.outputs.version }}-${{ steps.apk.outputs.short_sha }}-${{ steps.apk.outputs.architecture }}
path: |
${{ steps.apk.outputs.dir }}/*.apk
debug-release-notes.md
retention-days: 1