Merge pull request #290 from QueryaHub/issue/270-driver-manager-sqlite #38
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
| # Сборка Windows / Linux / macOS zip + GitHub Release. | ||
|
Check failure on line 1 in .github/workflows/release.yml
|
||
| # | ||
| # Автоматически: push тега X.Y.Z или vX.Y.Z. | ||
| # Имена zip берутся из semver в pubspec на закоммиченном ref (после merge в main он может | ||
| # быть новее номера тега из‑за version-bump — это не блокирует сборку, см. job version-hint). | ||
| # Вручную: Actions → Release → Run workflow (создаёт тег из pubspec, если его ещё нет). | ||
| name: Release | ||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| tags: | ||
| - '*.*.*' | ||
| - 'v*' | ||
| permissions: | ||
| contents: write | ||
| concurrency: | ||
| group: release-${{ github.ref }} | ||
| cancel-in-progress: false | ||
| jobs: | ||
| version-hint: | ||
| name: Version vs tag (hint only) | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Warn when git tag and pubspec semver differ | ||
| if: startsWith(github.ref, 'refs/tags/') | ||
| run: | | ||
| VER=$(grep '^version:' pubspec.yaml | sed 's/^version: //' | sed 's/+.*//') | ||
| RAW="${{ github.ref_name }}" | ||
| TAG="${RAW#v}" | ||
| if [ "$VER" != "$TAG" ]; then | ||
| echo "::warning::Git tag is $RAW but pubspec semver is $VER (часто так бывает после auto version-bump на main). Артефакты будут с именем **$VER** из pubspec; GitHub Release останется на теге **$RAW**. Чтобы всё совпадало, поставьте тег на semver из pubspec (например $VER)." | ||
| else | ||
| echo "Tag $RAW matches pubspec semver $VER." | ||
| fi | ||
| build-windows: | ||
| name: Build Windows | ||
| runs-on: windows-latest | ||
| outputs: | ||
| version: ${{ steps.version.outputs.version }} | ||
| full_version: ${{ steps.version.outputs.full_version }} | ||
| build_number: ${{ steps.version.outputs.build_number }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Get version from pubspec.yaml | ||
| id: version | ||
| shell: bash | ||
| run: | | ||
| FULL_VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //') | ||
| VERSION=$(echo "$FULL_VERSION" | sed 's/+.*//') | ||
| BUILD_NUMBER=$(echo "$FULL_VERSION" | sed 's/.*+//') | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "full_version=$FULL_VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "build_number=$BUILD_NUMBER" >> "$GITHUB_OUTPUT" | ||
| - name: Setup Flutter | ||
| uses: subosito/flutter-action@v2 | ||
| with: | ||
| flutter-version: '3.41.6' | ||
| channel: 'stable' | ||
| cache: true | ||
| - name: Get dependencies | ||
| run: flutter pub get | ||
| - name: Build Windows (release) | ||
| run: flutter build windows --release | ||
| - name: Zip Windows artifact | ||
| run: | | ||
| $v = "${{ steps.version.outputs.version }}" | ||
| $dir = "build\windows\x64\runner\Release" | ||
| Compress-Archive -Path "$dir\*" -DestinationPath "Querya-Desktop-$v-windows.zip" | ||
| - uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: bundle-windows | ||
| path: Querya-Desktop-${{ steps.version.outputs.version }}-windows.zip | ||
| if-no-files-found: error | ||
| build-linux: | ||
| name: Build Linux | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| version: ${{ steps.version.outputs.version }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Get version from pubspec.yaml | ||
| id: version | ||
| run: | | ||
| FULL_VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //') | ||
| VERSION=$(echo "$FULL_VERSION" | sed 's/+.*//') | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| - name: Install Linux dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev libsecret-1-dev | ||
| - name: Setup Flutter | ||
| uses: subosito/flutter-action@v2 | ||
| with: | ||
| flutter-version: '3.41.6' | ||
| channel: 'stable' | ||
| cache: true | ||
| - name: Get dependencies | ||
| run: flutter pub get | ||
| - name: Build Linux (release) | ||
| run: flutter build linux --release | ||
| - name: Zip Linux artifact | ||
| run: | | ||
| cd build/linux/x64/release/bundle | ||
| zip -r "${GITHUB_WORKSPACE}/Querya-Desktop-${{ steps.version.outputs.version }}-linux.zip" . | ||
| - uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: bundle-linux | ||
| path: Querya-Desktop-${{ steps.version.outputs.version }}-linux.zip | ||
| if-no-files-found: error | ||
| build-macos: | ||
| name: Build macOS | ||
| runs-on: macos-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Get version from pubspec.yaml | ||
| id: version | ||
| run: | | ||
| FULL_VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //') | ||
| VERSION=$(echo "$FULL_VERSION" | sed 's/+.*//') | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
| - name: Setup Flutter | ||
| uses: subosito/flutter-action@v2 | ||
| with: | ||
| flutter-version: '3.41.6' | ||
| channel: 'stable' | ||
| cache: true | ||
| - name: Get dependencies | ||
| run: flutter pub get | ||
| - name: Build macOS (release) | ||
| run: flutter build macos --release | ||
| - name: Sign and notarize macOS app | ||
| if: ${{ secrets.MACOS_SIGN_IDENTITY != '' && secrets.MACOS_NOTARY_KEY != '' }} | ||
| env: | ||
| MACOS_CERTIFICATE_P12: ${{ secrets.MACOS_CERTIFICATE_P12 }} | ||
| MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} | ||
| MACOS_SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }} | ||
| MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} | ||
| MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} | ||
| MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} | ||
| MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }} | ||
| run: | | ||
| set -euo pipefail | ||
| APP="build/macos/Build/Products/Release/querya_desktop.app" | ||
| test -d "$APP" | ||
| KEYCHAIN="$RUNNER_TEMP/build.keychain" | ||
| security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" "$KEYCHAIN" | ||
| security set-keychain-settings -lut 1200 "$KEYCHAIN" | ||
| security default-keychain -s "$KEYCHAIN" | ||
| security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" "$KEYCHAIN" | ||
| echo "$MACOS_CERTIFICATE_P12" | base64 --decode -o "$RUNNER_TEMP/certificate.p12" | ||
| security import "$RUNNER_TEMP/certificate.p12" -k "$KEYCHAIN" -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign | ||
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_KEYCHAIN_PASSWORD" "$KEYCHAIN" | ||
| # Sign nested code from the inside out (avoids --deep pitfalls). | ||
| find "$APP/Contents/Frameworks" -type f \( -name "*.dylib" -o -name "*.so" \) -exec \ | ||
| codesign --force --timestamp --options runtime --sign "$MACOS_SIGN_IDENTITY" {} + | ||
| find "$APP/Contents/Frameworks" -type d -name "*.framework" -exec \ | ||
| codesign --force --timestamp --options runtime --sign "$MACOS_SIGN_IDENTITY" {} + | ||
| find "$APP/Contents/MacOS" -maxdepth 1 -type f -exec \ | ||
| codesign --force --timestamp --options runtime --sign "$MACOS_SIGN_IDENTITY" {} + | ||
| # Sign the main app bundle with hardened runtime and signed entitlements. | ||
| codesign --force --timestamp --options runtime \ | ||
| --entitlements macos/Runner/ReleaseSigned.entitlements \ | ||
| --sign "$MACOS_SIGN_IDENTITY" "$APP" | ||
| codesign --verify --deep --strict --verbose=2 "$APP" | ||
| NOTARY_KEY="$RUNNER_TEMP/notary_key.p8" | ||
| echo -n "$MACOS_NOTARY_KEY" | base64 --decode -o "$NOTARY_KEY" | ||
| ditto -c -k --keepParent "$APP" "$RUNNER_TEMP/notarize.zip" | ||
| xcrun notarytool submit "$RUNNER_TEMP/notarize.zip" \ | ||
| --key "$NOTARY_KEY" \ | ||
| --key-id "$MACOS_NOTARY_KEY_ID" \ | ||
| --issuer "$MACOS_NOTARY_ISSUER_ID" \ | ||
| --wait | ||
| xcrun stapler staple "$APP" | ||
| rm "$NOTARY_KEY" | ||
| - name: Zip macOS .app | ||
| run: | | ||
| APP="build/macos/Build/Products/Release/querya_desktop.app" | ||
| test -d "$APP" | ||
| ditto -c -k --keepParent "$APP" "Querya-Desktop-${{ steps.version.outputs.version }}-macos.zip" | ||
| - uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: bundle-macos | ||
| path: Querya-Desktop-${{ steps.version.outputs.version }}-macos.zip | ||
| if-no-files-found: error | ||
| publish: | ||
| name: Publish GitHub Release | ||
| needs: [build-windows, build-linux, build-macos] | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - uses: actions/download-artifact@v4 | ||
| with: | ||
| path: artifacts | ||
| pattern: bundle-* | ||
| merge-multiple: true | ||
| - name: Layout distribution files | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p dist | ||
| find artifacts -name '*.zip' -exec mv -t dist/ {} + | ||
| test "$(find dist -name '*.zip' | wc -l)" -eq 3 | ||
| cd dist | ||
| sha256sum *.zip | tee SHA256SUMS.txt | ||
| - name: Build release notes from CHANGELOG.md | ||
| run: | | ||
| set -euo pipefail | ||
| VERSION="${{ needs.build-windows.outputs.version }}" | ||
| ./scripts/extract-changelog-section.sh "$VERSION" > release-notes.md | ||
| { | ||
| echo "" | ||
| echo "---" | ||
| echo "" | ||
| echo "### Downloads" | ||
| echo "- **Linux**: \`Querya-Desktop-${VERSION}-linux.zip\`" | ||
| echo "- **Windows**: \`Querya-Desktop-${VERSION}-windows.zip\`" | ||
| echo "- **macOS**: \`Querya-Desktop-${VERSION}-macos.zip\` (signed, notarized and stapled \`.app\` when Apple Developer secrets are configured; otherwise unsigned)" | ||
| echo "" | ||
| echo "Verify checksums: \`SHA256SUMS.txt\`" | ||
| echo "" | ||
| echo "### Build info" | ||
| echo "- **pubspec**: ${{ needs.build-windows.outputs.full_version }}" | ||
| echo "- **Commit**: ${{ github.sha }}" | ||
| } >> release-notes.md | ||
| - name: Release tag name | ||
| id: rel | ||
| run: | | ||
| if [ "${{ github.ref_type }}" = "tag" ]; then | ||
| echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "tag=${{ needs.build-windows.outputs.version }}" >> "$GITHUB_OUTPUT" | ||
| fi | ||
| - name: Create GitHub Release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| tag_name: ${{ steps.rel.outputs.tag }} | ||
| name: Querya Desktop ${{ needs.build-windows.outputs.version }} | ||
| body_path: release-notes.md | ||
| fail_on_unmatched_files: true | ||
| files: | | ||
| dist/*.zip | ||
| dist/SHA256SUMS.txt | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||