|
1 | 1 | name: Release APKs
|
2 | 2 |
|
3 | 3 | on:
|
4 |
| - release: |
5 |
| - types: |
6 |
| - - published |
7 |
| - workflow_dispatch: |
8 |
| - inputs: |
9 |
| - tag_name: |
10 |
| - description: "Existing release tag to upload assets to (required for manual runs)" |
11 |
| - required: false |
12 |
| - type: string |
13 |
| - flavor: |
14 |
| - description: "Which flavor to build" |
15 |
| - type: choice |
16 |
| - required: true |
17 |
| - options: |
18 |
| - - oss |
19 |
| - - fdroid |
20 |
| - - both |
21 |
| - default: both |
22 |
| - build_type: |
23 |
| - description: "APK Build Type (split per ABI or single universal)" |
24 |
| - type: choice |
25 |
| - required: true |
26 |
| - options: |
27 |
| - - split |
28 |
| - - single |
29 |
| - default: split |
30 |
| - run_tests: |
31 |
| - description: "Run Flutter tests before building APKs" |
32 |
| - type: boolean |
33 |
| - required: true |
34 |
| - default: false |
| 4 | + # 既存: Release publish 時 |
| 5 | + release: |
| 6 | + types: |
| 7 | + - published |
| 8 | + # 新規: タグ push (publish-release.yml が vX.Y.Z を作成した直後) でも起動 |
| 9 | + push: |
| 10 | + tags: |
| 11 | + - "v[0-9]*" |
| 12 | + workflow_dispatch: |
| 13 | + inputs: |
| 14 | + tag_name: |
| 15 | + description: "Existing release tag to upload assets to (required for manual runs)" |
| 16 | + required: false |
| 17 | + type: string |
| 18 | + flavor: |
| 19 | + description: "Which flavor to build" |
| 20 | + type: choice |
| 21 | + required: true |
| 22 | + options: |
| 23 | + - oss |
| 24 | + - fdroid |
| 25 | + - both |
| 26 | + default: both |
| 27 | + build_type: |
| 28 | + description: "APK Build Type (split per ABI or single universal)" |
| 29 | + type: choice |
| 30 | + required: true |
| 31 | + options: |
| 32 | + - split |
| 33 | + - single |
| 34 | + default: split |
| 35 | + run_tests: |
| 36 | + description: "Run Flutter tests before building APKs" |
| 37 | + type: boolean |
| 38 | + required: true |
| 39 | + default: false |
35 | 40 |
|
36 | 41 | permissions:
|
37 |
| - contents: write |
| 42 | + contents: write |
38 | 43 |
|
39 | 44 | concurrency:
|
40 |
| - group: release-apk-${{ github.event.release.tag_name || github.event.inputs.tag_name || github.ref }} |
41 |
| - cancel-in-progress: false |
| 45 | + group: release-apk-${{ github.event.release.tag_name || github.event.inputs.tag_name || github.ref }} |
| 46 | + cancel-in-progress: false |
42 | 47 |
|
43 | 48 | jobs:
|
44 |
| - build_and_attach: |
45 |
| - name: Build and attach APKs |
46 |
| - runs-on: ubuntu-latest |
| 49 | + build_and_attach: |
| 50 | + name: Build and attach APKs |
| 51 | + runs-on: ubuntu-latest |
| 52 | + env: |
| 53 | + BUILD_TYPE: ${{ github.event.inputs.build_type || 'split' }} |
| 54 | + FLAVOR: ${{ github.event.inputs.flavor || 'both' }} |
| 55 | + steps: |
| 56 | + - name: Checkout code |
| 57 | + uses: actions/checkout@v4 |
| 58 | + with: |
| 59 | + fetch-depth: 0 |
| 60 | + |
| 61 | + - name: Set up JDK 21 |
| 62 | + uses: actions/setup-java@v4 |
| 63 | + with: |
| 64 | + distribution: "temurin" |
| 65 | + java-version: "21" |
| 66 | + |
| 67 | + - name: Set up Flutter |
| 68 | + uses: subosito/flutter-action@v2 |
| 69 | + with: |
| 70 | + channel: stable |
| 71 | + cache: true |
| 72 | + |
| 73 | + - name: Get Flutter dependencies |
| 74 | + run: flutter pub get || flutter pub get || flutter pub get |
| 75 | + |
| 76 | + - name: Analyze project source (optional) |
| 77 | + if: ${{ github.event.inputs.run_tests == 'true' }} |
| 78 | + run: flutter analyze --no-fatal-warnings || true |
| 79 | + |
| 80 | + - name: Run tests (optional) |
| 81 | + if: ${{ github.event.inputs.run_tests == 'true' }} |
| 82 | + run: flutter test |
| 83 | + |
| 84 | + - name: Determine target release tag |
| 85 | + id: release_meta |
47 | 86 | env:
|
48 |
| - BUILD_TYPE: ${{ github.event.inputs.build_type || 'split' }} |
49 |
| - FLAVOR: ${{ github.event.inputs.flavor || 'both' }} |
50 |
| - steps: |
51 |
| - - name: Checkout code |
52 |
| - uses: actions/checkout@v4 |
53 |
| - with: |
54 |
| - fetch-depth: 0 |
55 |
| - |
56 |
| - - name: Set up JDK 21 |
57 |
| - uses: actions/setup-java@v4 |
58 |
| - with: |
59 |
| - distribution: "temurin" |
60 |
| - java-version: "21" |
61 |
| - |
62 |
| - - name: Set up Flutter |
63 |
| - uses: subosito/flutter-action@v2 |
64 |
| - with: |
65 |
| - channel: stable |
66 |
| - cache: true |
67 |
| - |
68 |
| - - name: Get Flutter dependencies |
69 |
| - run: flutter pub get || flutter pub get || flutter pub get |
70 |
| - |
71 |
| - - name: Analyze project source (optional) |
72 |
| - if: ${{ github.event.inputs.run_tests == 'true' }} |
73 |
| - run: flutter analyze --no-fatal-warnings || true |
74 |
| - |
75 |
| - - name: Run tests (optional) |
76 |
| - if: ${{ github.event.inputs.run_tests == 'true' }} |
77 |
| - run: flutter test |
78 |
| - |
79 |
| - - name: Determine target release tag |
80 |
| - id: release_meta |
81 |
| - env: |
82 |
| - EVENT_NAME: ${{ github.event_name }} |
83 |
| - RELEASE_TAG: ${{ github.event.release.tag_name }} |
84 |
| - INPUT_TAG: ${{ github.event.inputs.tag_name }} |
85 |
| - run: | |
86 |
| - if [ "$EVENT_NAME" = "release" ]; then |
87 |
| - if [ -z "$RELEASE_TAG" ]; then |
88 |
| - echo "::error::Release tag not detected." >&2 |
89 |
| - exit 1 |
90 |
| - fi |
91 |
| - echo "tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT" |
92 |
| - else |
93 |
| - if [ -z "$INPUT_TAG" ]; then |
94 |
| - echo "::error::Please provide tag_name when running manually." >&2 |
95 |
| - exit 1 |
96 |
| - fi |
97 |
| - echo "tag=$INPUT_TAG" >> "$GITHUB_OUTPUT" |
98 |
| - fi |
99 |
| -
|
100 |
| - - name: Build APK (Split per ABI, OSS) |
101 |
| - if: ${{ contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
102 |
| - run: flutter build apk --flavor oss --release --split-per-abi --build-number=${{ github.run_number }} |
103 |
| - |
104 |
| - - name: Build APK (Split per ABI, FDroid) |
105 |
| - if: ${{ contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
106 |
| - run: flutter build apk --flavor fdroid --release --split-per-abi --build-number=${{ github.run_number }} --dart-define=ENABLE_SELF_UPDATE=false |
107 |
| - |
108 |
| - - name: Build APK (Single Universal, OSS) |
109 |
| - if: ${{ contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
110 |
| - run: flutter build apk --flavor oss --release --build-number=${{ github.run_number }} |
111 |
| - |
112 |
| - - name: Build APK (Single Universal, FDroid) |
113 |
| - if: ${{ contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
114 |
| - run: flutter build apk --flavor fdroid --release --build-number=${{ github.run_number }} --dart-define=ENABLE_SELF_UPDATE=false |
115 |
| - |
116 |
| - - name: Upload Split APKs (OSS) |
117 |
| - if: ${{ contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
118 |
| - uses: softprops/action-gh-release@v2 |
119 |
| - with: |
120 |
| - tag_name: ${{ steps.release_meta.outputs.tag }} |
121 |
| - draft: false |
122 |
| - prerelease: false |
123 |
| - files: build/app/outputs/flutter-apk/app-oss-*-release.apk |
124 |
| - |
125 |
| - - name: Upload Split APKs (FDroid) |
126 |
| - if: ${{ contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
127 |
| - uses: softprops/action-gh-release@v2 |
128 |
| - with: |
129 |
| - tag_name: ${{ steps.release_meta.outputs.tag }} |
130 |
| - draft: false |
131 |
| - prerelease: false |
132 |
| - files: build/app/outputs/flutter-apk/app-fdroid-*-release.apk |
133 |
| - |
134 |
| - - name: Upload Single APK (OSS) |
135 |
| - if: ${{ contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
136 |
| - uses: softprops/action-gh-release@v2 |
137 |
| - with: |
138 |
| - tag_name: ${{ steps.release_meta.outputs.tag }} |
139 |
| - draft: false |
140 |
| - prerelease: false |
141 |
| - files: build/app/outputs/flutter-apk/app-oss-release.apk |
142 |
| - |
143 |
| - - name: Upload Single APK (FDroid) |
144 |
| - if: ${{ contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
145 |
| - uses: softprops/action-gh-release@v2 |
146 |
| - with: |
147 |
| - tag_name: ${{ steps.release_meta.outputs.tag }} |
148 |
| - draft: false |
149 |
| - prerelease: false |
150 |
| - files: build/app/outputs/flutter-apk/app-fdroid-release.apk |
| 87 | + EVENT_NAME: ${{ github.event_name }} |
| 88 | + RELEASE_TAG: ${{ github.event.release.tag_name }} |
| 89 | + INPUT_TAG: ${{ github.event.inputs.tag_name }} |
| 90 | + GITHUB_REF: ${{ github.ref }} |
| 91 | + run: | |
| 92 | + set -e |
| 93 | + case "$EVENT_NAME" in |
| 94 | + release) |
| 95 | + if [ -z "$RELEASE_TAG" ]; then echo "::error::Release tag not detected." >&2; exit 1; fi |
| 96 | + TAG="$RELEASE_TAG" ;; |
| 97 | + push) |
| 98 | + # refs/tags/v1.2.3 -> v1.2.3 |
| 99 | + TAG="${GITHUB_REF##refs/tags/}" ;; |
| 100 | + workflow_dispatch) |
| 101 | + if [ -z "$INPUT_TAG" ]; then echo "::error::Please provide tag_name when running manually." >&2; exit 1; fi |
| 102 | + TAG="$INPUT_TAG" ;; |
| 103 | + *) echo "::error::Unsupported event $EVENT_NAME" >&2; exit 1 ;; |
| 104 | + esac |
| 105 | + echo "tag=$TAG" >> "$GITHUB_OUTPUT" |
| 106 | + echo "Using tag: $TAG" |
| 107 | +
|
| 108 | + - name: Skip if assets already present |
| 109 | + id: maybe_skip |
| 110 | + env: |
| 111 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 112 | + run: | |
| 113 | + set -e |
| 114 | + TAG='${{ steps.release_meta.outputs.tag }}' |
| 115 | + # 既に同タグのリリースがあり、且つ apk 資産が1つでもあるならスキップ |
| 116 | + API="https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" |
| 117 | + RESP=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" -H 'Accept: application/vnd.github+json' "$API" || true) |
| 118 | + if echo "$RESP" | grep -q '"assets"'; then |
| 119 | + COUNT=$(echo "$RESP" | jq '[.assets[] | select(.name|test("apk$"))] | length') |
| 120 | + echo "Existing APK asset count: $COUNT" |
| 121 | + if [ "$COUNT" -gt 0 ]; then |
| 122 | + echo "skip=true" >> $GITHUB_OUTPUT |
| 123 | + echo "Detected existing APK assets. Skipping build/upload." |
| 124 | + else |
| 125 | + echo "skip=false" >> $GITHUB_OUTPUT |
| 126 | + fi |
| 127 | + else |
| 128 | + echo "skip=false" >> $GITHUB_OUTPUT |
| 129 | + fi |
| 130 | +
|
| 131 | + - name: Build APK (Split per ABI, OSS) |
| 132 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
| 133 | + run: flutter build apk --flavor oss --release --split-per-abi --build-number=${{ github.run_number }} |
| 134 | + |
| 135 | + - name: Build APK (Split per ABI, FDroid) |
| 136 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
| 137 | + run: flutter build apk --flavor fdroid --release --split-per-abi --build-number=${{ github.run_number }} --dart-define=ENABLE_SELF_UPDATE=false |
| 138 | + |
| 139 | + - name: Build APK (Single Universal, OSS) |
| 140 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
| 141 | + run: flutter build apk --flavor oss --release --build-number=${{ github.run_number }} |
| 142 | + |
| 143 | + - name: Build APK (Single Universal, FDroid) |
| 144 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
| 145 | + run: flutter build apk --flavor fdroid --release --build-number=${{ github.run_number }} --dart-define=ENABLE_SELF_UPDATE=false |
| 146 | + |
| 147 | + - name: Upload Split APKs (OSS) |
| 148 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
| 149 | + uses: softprops/action-gh-release@v2 |
| 150 | + with: |
| 151 | + tag_name: ${{ steps.release_meta.outputs.tag }} |
| 152 | + draft: false |
| 153 | + prerelease: false |
| 154 | + files: build/app/outputs/flutter-apk/app-oss-*-release.apk |
| 155 | + |
| 156 | + - name: Upload Split APKs (FDroid) |
| 157 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'split') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
| 158 | + uses: softprops/action-gh-release@v2 |
| 159 | + with: |
| 160 | + tag_name: ${{ steps.release_meta.outputs.tag }} |
| 161 | + draft: false |
| 162 | + prerelease: false |
| 163 | + files: build/app/outputs/flutter-apk/app-fdroid-*-release.apk |
| 164 | + |
| 165 | + - name: Upload Single APK (OSS) |
| 166 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'oss' || env.FLAVOR == 'both') }} |
| 167 | + uses: softprops/action-gh-release@v2 |
| 168 | + with: |
| 169 | + tag_name: ${{ steps.release_meta.outputs.tag }} |
| 170 | + draft: false |
| 171 | + prerelease: false |
| 172 | + files: build/app/outputs/flutter-apk/app-oss-release.apk |
| 173 | + |
| 174 | + - name: Upload Single APK (FDroid) |
| 175 | + if: ${{ steps.maybe_skip.outputs.skip != 'true' && contains(env.BUILD_TYPE, 'single') && (env.FLAVOR == 'fdroid' || env.FLAVOR == 'both') }} |
| 176 | + uses: softprops/action-gh-release@v2 |
| 177 | + with: |
| 178 | + tag_name: ${{ steps.release_meta.outputs.tag }} |
| 179 | + draft: false |
| 180 | + prerelease: false |
| 181 | + files: build/app/outputs/flutter-apk/app-fdroid-release.apk |
0 commit comments