DEV Community

Cover image for GSoC Week 5: Markdown broke, CI/CD woke
Yashvant Singh
Yashvant Singh

Posted on

GSoC Week 5: Markdown broke, CI/CD woke

So this week started with me working on the buggy Interactive Book part of the app. We hit this error:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞══  
'package:flutter_markdown/src/builder.dart': Failed assertion: line 267 pos 12: '_inlines.isEmpty': is not true.
Enter fullscreen mode Exit fullscreen mode

The widget causing it was:

SingleChildScrollView:file:///C:/Users/emper/Desktop/cv_app_gsoc/lib/ui/views/ib/ib_page_view.dart:501:22
Enter fullscreen mode Exit fullscreen mode

This is an assertion failure in the flutter_markdown package, and basically, the parser found some weird inline elements in our Markdown that it couldn’t handle. Either some broken tags or bad formatting. Now we were already using a sanitizeMarkdown() function (I’d mentioned that in the last blog), to catch broken lines and tags but still, this popped up.

Digging deeper, I noticed this in our custom builders:

RegExp get pattern => RegExp(r'{:\s?(.+)\s?}');
Enter fullscreen mode Exit fullscreen mode

This is for extracting content between {: and }. We had more such patterns, and I was trying all ways to fix things from the UI side wrapping in an error boundary, adding debug logs, etc.

Also ran into a null operator used on a null value kind of thing, so I added proper checks for that as well.


But then… Hardik pinged

Hardik asked me to pause this bug-hunt for a while and work on releasing the app — a basic GitHub release so others in the community can try it too.

This was literally the first time I was doing anything with CI/CD — had zero idea about it 😅. So I just told my mentors: “Yeh we can do that, but I don’t have much knowledge on this… could you share something I can start with?”

Hardik shared this article:
👉 Automating Flutter Builds with GitHub Actions: A Step-by-Step Guide

It was actually really well written and easy to understand. But in that article, they used a single file for the workflow.

In our project, we had three files: main.yml, ci.yml, and cd.yml.

So I read more and turns out it’s perfectly fine. You use one file if your project is small, but for a bit more structure, people prefer separate files. In our case:

  • main.yml: Just validates commit messages (we're using action-conventional-commits). Triggers on pull_request.

  • ci.yml: Handles build, test, and code checks (formatting, analysis, coverage). Runs on every push/PR.

  • cd.yml: Manages release and deployment using semantic-release, Fastlane, GitHub Releases, etc. Triggers manually or on push to master.


What I added

I added this part to build and upload the APK:

- name: Build APK (Android)
  if: ${{ matrix.platform == 'ubuntu-latest' }}
  run: |
    flutter build apk --release \
      --dart-define=FB_APP_ID=${{ secrets.FB_APP_ID }} \
      --dart-define=FB_APP_NAME=${{ secrets.FB_APP_NAME }} \
      --dart-define=GITHUB_OAUTH_CLIENT_ID=${{ secrets.GH_OAUTH_CLIENT_ID }} \
      --dart-define=GITHUB_OAUTH_CLIENT_SECRET=${{ secrets.GH_OAUTH_CLIENT_SECRET }}

- name: Upload APK Artifact
  if: ${{ matrix.platform == 'ubuntu-latest' }}
  uses: actions/upload-artifact@v4
  with:
    name: android-apk-${{ github.run_number }}
    path: build/app/outputs/apk/release/app-release.apk
    if-no-files-found: error
Enter fullscreen mode Exit fullscreen mode

Then I added the release section to automate GitHub release creation when code is pushed to master:

release:
  if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
  needs: build
  runs-on: ubuntu-latest
  steps:
    - name: Download APK Artifact
      uses: actions/download-artifact@v4
      with:
        name: android-apk-${{ github.run_number }}
        path: ./

    - name: Get Current Date
      id: date
      run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT

    - name: Create Release
      uses: softprops/action-gh-release@v2
      with:
        tag_name: "v1.0.${{ github.run_number }}"
        name: "Release v1.0.${{ github.run_number }} - ${{ steps.date.outputs.date }}"
        body: |
          Android APK release built from commit ${{ github.sha }}.

          Build number: ${{ github.run_number }}
          Build date: ${{ steps.date.outputs.date }}

          Download and install the APK file below.
        files: ./app-release.apk
        draft: false
        prerelease: false
        generate_release_notes: true
Enter fullscreen mode Exit fullscreen mode

To try what I learnt, I created a separate repo and tried out the learning here:
👉 Learning GitHub Workflow

The PR : Enhance CI with automated releases #398

After this, Hardik made the release public in the community and shared the APK. And guess what — people actually downloaded and ran it!


And then... F-Droid?

Someone in the community — salmoneatenbybear aka Aditya (I hope I’m right 😅) — mentioned F-Droid deployment. I’ll be honest, I didn’t know what F-Droid was at that moment.

So I looked it up.

Turns out:

F-Droid is a free and open-source app store for Android.
It doesn’t track users, hosts only FOSS apps, and is maintained by the community.

It’s kinda like Play Store, but for open-source-only apps. Very cool.

I tried checking the last PR related to it (or maybe it wasn’t a PR), but it didn’t really come to a conclusion. Still need to explore it more.

If you're curious about how to contribute or deploy on F-Droid, here’s a good starting point: 📘 F-Droid Contribution Guide


Wrapping up...

So yeah — started the week trying to make Markdown behave, ended the week building CI/CD pipelines, publishing GitHub releases, and learning about app stores I never knew existed 😄

Next up: probably explore more around F-Droid, improve release notes, and see if I can finally fix that Markdown crash for good.

Thanks for reading! If you have suggestions, feel free to drop them in comments 🙌


Top comments (0)