name: Continuous Delivery on: push: branches: - main pull_request: release: types: - published jobs: # The "Docker" job builds the Docker image and pushes it to the GitHub Container Registry. The job only runs when a # commit is pushed to the main branch or a new tag is created. docker: name: Docker runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' || (github.event_name == 'release' && github.event.action == 'published') permissions: contents: read packages: write steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set Docker Tag id: tag run: | if [[ $GITHUB_REF == refs/tags/* ]]; then echo TAG=${GITHUB_REF:10} >> $GITHUB_ENV else echo TAG=main >> $GITHUB_ENV fi - name: Setup QEMU uses: docker/setup-qemu-action@v3 - name: Setup Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io - name: Build and Push Docker Image id: docker_build uses: docker/build-push-action@v5 with: push: true context: ./supabase/functions file: ./supabase/functions/_cmd/Dockerfile platforms: linux/amd64,linux/arm64/v8 tags: ghcr.io/${{ github.repository_owner }}/feeddeck:${{ env.TAG }} # The "Supabase" job runs the database migrations and deploys all Supabase functions. The job only runs when a commit # is pushed to the main branch or a new tag is created. supabase: name: Supabase runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' || (github.event_name == 'release' && github.event.action == 'published') permissions: contents: read steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Supabase uses: supabase/setup-cli@v1 - name: Push Database Migration and Deploy Functions if: github.ref == 'refs/heads/main' env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_STAGE_DB_PASSWORD }} PROJECT_ID: ${{ secrets.SUPABASE_STAGE_PROJECT_ID }} run: | supabase link --project-ref $PROJECT_ID supabase db push supabase functions deploy add-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy delete-user-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy generate-magic-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy profile-v2 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy stripe-create-checkout-session-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json - name: Push Database Migration and Deploy Functions if: ${{ github.event_name == 'release' && github.event.action == 'published' }} env: SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_PROD_DB_PASSWORD }} PROJECT_ID: ${{ secrets.SUPABASE_PROD_PROJECT_ID }} run: | supabase link --project-ref $PROJECT_ID supabase db push supabase functions deploy add-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy delete-user-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy generate-magic-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy profile-v2 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy stripe-create-checkout-session-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json # The "Web" job builds the Flutter web app and publishes it to Cloudflare Pages. The job only runs when a commit is # pushed to the main branch or a new tag is created. web: name: Web runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' || (github.event_name == 'release' && github.event.action == 'published') permissions: contents: read defaults: run: working-directory: "app" steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Packages run: | # Required for Flutter sudo apt-get update -y sudo apt-get install -y ninja-build libgtk-3-dev - name: Set Environment Variables id: tag run: | if [[ $GITHUB_REF == refs/tags/* ]]; then echo CLOUDFLARE_PROJECT_NAME=${{ secrets.CLOUDFLARE_PROJECT_NAME_PROD }} >> $GITHUB_ENV echo SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} >> $GITHUB_ENV echo SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} >> $GITHUB_ENV echo SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} >> $GITHUB_ENV echo GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }} >> $GITHUB_ENV else echo CLOUDFLARE_PROJECT_NAME=${{ secrets.CLOUDFLARE_PROJECT_NAME_STAGE }} >> $GITHUB_ENV echo SUPABASE_URL=${{ secrets.SUPABASE_STAGE_URL }} >> $GITHUB_ENV echo SUPABASE_ANON_KEY=${{ secrets.SUPABASE_STAGE_ANON_KEY }} >> $GITHUB_ENV echo SUPABASE_SITE_URL=${{ secrets.SUPABASE_STAGE_SITE_URL }} >> $GITHUB_ENV echo GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_STAGE_GOOGLE_CLIENT_ID }} >> $GITHUB_ENV fi - name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: '3.13.7' channel: 'stable' cache: true cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' - name: Install Dependencies run: | flutter pub get - name: Build run: | flutter config --enable-web flutter build web --release --dart-define SUPABASE_URL=${{ env.SUPABASE_URL }} --dart-define SUPABASE_ANON_KEY=${{ env.SUPABASE_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ env.SUPABASE_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID }} - name: Publish to Cloudflare Pages uses: cloudflare/pages-action@v1 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} projectName: ${{ env.CLOUDFLARE_PROJECT_NAME }} directory: ./app/build/web branch: main # The "macOS" job builds the Flutter macOS app and uploads it to the GitHub release or the pull request. The job only # runs for pull requests and when a new release is published. macos: name: macOS runs-on: macos-latest if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published') permissions: contents: write defaults: run: working-directory: "app" steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: '3.13.7' channel: 'stable' cache: true cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' - name: Install Dependencies run: | flutter pub get - name: Build run: | flutter config --enable-macos-desktop FLUTTER_XCODE_CODE_SIGN_IDENTITY="" FLUTTER_XCODE_CODE_SIGNING_REQUIRED=NO flutter build macos --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }} - name: Package run: | ditto -c -k --keepParent "build/macos/Build/Products/Release/FeedDeck.app" "build/macos/Build/Products/Release/feeddeck-macos-universal.zip" - name: Upload Artifacts (PR) if: ${{ github.event_name == 'pull_request' }} uses: actions/upload-artifact@v3 with: name: feeddeck-macos-universal.zip path: app/build/macos/Build/Products/Release/feeddeck-macos-universal.zip if-no-files-found: error - name: Upload Artifacts (Release) uses: shogo82148/actions-upload-release-asset@v1 if: ${{ github.event_name == 'release' && github.event.action == 'published' }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: app/build/macos/Build/Products/Release/feeddeck-macos-universal.zip # The "Linux" job builds the Flutter Linux app and uploads it to the GitHub release or the pull request. The job only # runs for pull requests and when a new release is published. linux: name: Linux runs-on: ubuntu-latest if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published') permissions: contents: write defaults: run: working-directory: "app" steps: - name: Checkout uses: actions/checkout@v4 - name: Install Packages run: | # Required for Flutter sudo apt-get update -y sudo apt-get install -y ninja-build libgtk-3-dev # Required for Package "media_kit" which is used via "just_audio_media_kit" for Linux and Windows: # See: https://pub.dev/packages/media_kit and https://pub.dev/packages/just_audio_media_kit sudo apt-get install -y libmpv-dev mpv - name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: '3.13.7' channel: 'stable' cache: true cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' - name: Install Dependencies run: | flutter pub get - name: Build run: | flutter config --enable-linux-desktop flutter build linux --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }} - name: Package run: | cp linux/flatpak/app.feeddeck.feeddeck.desktop build/linux/x64/release/bundle/ cp linux/flatpak/app.feeddeck.feeddeck.metainfo.xml build/linux/x64/release/bundle/ cp linux/flatpak/app.feeddeck.feeddeck.svg build/linux/x64/release/bundle/ cd build cp -r linux/x64/release/bundle/ feeddeck-linux-x86_64 tar -czf feeddeck-linux-x86_64.tar.gz feeddeck-linux-x86_64 - name: Upload Artifacts (PR) if: ${{ github.event_name == 'pull_request' }} uses: actions/upload-artifact@v3 with: name: feeddeck-linux-x86_64.tar.gz path: app/build/feeddeck-linux-x86_64.tar.gz if-no-files-found: error - name: Upload Artifacts (Release) uses: shogo82148/actions-upload-release-asset@v1 if: ${{ github.event_name == 'release' && github.event.action == 'published' }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: app/build/feeddeck-linux-x86_64.tar.gz # The "Windows" job builds the Flutter Windows app and uploads it to the GitHub release or the pull request. The job # only runs for pull requests and when a new release is published. windows: name: Windows runs-on: windows-latest if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published') permissions: contents: write defaults: run: working-directory: "app" steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: '3.13.7' channel: 'stable' cache: true cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:' cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:' - name: Install Dependencies run: | flutter pub get - name: Build run: | flutter config --enable-windows-desktop flutter build windows --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }} - name: Package run: | flutter pub run msix:create --output-path build --output-name feeddeck cd build 7z a -tzip feeddeck-windows-x86_64.zip feeddeck.msix - name: Upload Artifacts (PR) if: ${{ github.event_name == 'pull_request' }} uses: actions/upload-artifact@v3 with: name: feeddeck-windows-x86_64.zip path: app/build/feeddeck-windows-x86_64.zip if-no-files-found: error - name: Upload Artifacts (Release) uses: shogo82148/actions-upload-release-asset@v1 if: ${{ github.event_name == 'release' && github.event.action == 'published' }} with: upload_url: ${{ github.event.release.upload_url }} asset_path: app/build/feeddeck-windows-x86_64.zip