Bird
Raised Fist0
Android Kotlinmobile~20 mins

CI/CD with GitHub Actions in Android Kotlin - Mini App: Build & Ship

Choose your learning style10 modes available
Build: CI/CD Pipeline Setup
This screen helps you set up a basic Continuous Integration and Continuous Deployment (CI/CD) pipeline for an Android Kotlin app using GitHub Actions. It shows the workflow file structure and explains how to automate build and test on every push.
Target UI
----------------------------------
| CI/CD Pipeline Setup            |
|--------------------------------|
| Workflow File:                 |
| .github/workflows/android.yml |
|                                |
| Steps:                        |
| 1. Checkout code              |
| 2. Set up JDK                |
| 3. Build debug APK            |
| 4. Run unit tests             |
|                                |
| [Save Workflow] [Cancel]      |
----------------------------------
Show a text area with sample GitHub Actions YAML workflow for Android Kotlin
Include buttons: 'Save Workflow' and 'Cancel'
Display step-by-step explanation of the workflow
Use simple UI with clear labels and readable font
Starter Code
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      MaterialTheme {
        Surface(modifier = Modifier.padding(16.dp)) {
          // TODO: Add your code here
        }
      }
    }
  }
}
Task 1
Task 2
Task 3
Solution
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      MaterialTheme {
        Surface(modifier = Modifier.padding(16.dp)) {
          CiCdSetupScreen()
        }
      }
    }
  }
}

@Composable
fun CiCdSetupScreen() {
  val yamlContent = remember { mutableStateOf(
    "name: Android CI\non: [push]\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - name: Set up JDK 17\n        uses: actions/setup-java@v3\n        with:\n          distribution: 'temurin'\n          java-version: '17'\n      - name: Build Debug APK\n        run: ./gradlew assembleDebug\n      - name: Run Unit Tests\n        run: ./gradlew test"
  ) }

  Column {
    Text(text = "GitHub Actions Workflow YAML", style = MaterialTheme.typography.titleMedium)
    Spacer(modifier = Modifier.height(8.dp))
    TextField(
      value = yamlContent.value,
      onValueChange = { yamlContent.value = it },
      modifier = Modifier.height(200.dp),
      readOnly = true
    )
    Spacer(modifier = Modifier.height(16.dp))
    Text(text = "Steps Explanation:")
    Text(text = "1. Checkout code: Gets your app code from GitHub.")
    Text(text = "2. Set up JDK 17: Prepares Java environment for building.")
    Text(text = "3. Build Debug APK: Compiles your app into an APK file.")
    Text(text = "4. Run Unit Tests: Runs your app's tests to check for errors.")
    Spacer(modifier = Modifier.height(24.dp))
    Button(onClick = { /* Save workflow action */ }) {
      Text(text = "Save Workflow")
    }
    Spacer(modifier = Modifier.height(8.dp))
    Button(onClick = { /* Cancel action */ }) {
      Text(text = "Cancel")
    }
  }
}

This screen uses Jetpack Compose to create a simple UI showing a GitHub Actions workflow YAML for Android Kotlin CI/CD.

The TextField displays the YAML content in a read-only box so users can see the exact workflow steps.

Below, Text components explain each step in simple words, helping beginners understand the process.

Two buttons let users save or cancel the workflow setup (actions are placeholders here).

The UI uses padding and spacing for clarity and readability.

Final Result
Completed Screen
----------------------------------
| CI/CD Pipeline Setup            |
|--------------------------------|
| GitHub Actions Workflow YAML   |
| ------------------------------ |
| name: Android CI               |
| on: [push]                    |
| jobs:                        |
|   build:                     |
|     runs-on: ubuntu-latest    |
|     steps:                   |
|       - uses: actions/checkout|
|       - name: Set up JDK 17  |
|         uses: actions/setup-java|
|       - name: Build Debug APK |
|         run: ./gradlew assembleDebug|
|       - name: Run Unit Tests  |
|         run: ./gradlew test   |
|                              |
| Steps Explanation:            |
| 1. Checkout code: Gets your app|
| 2. Set up JDK 17: Prepares Java|
| 3. Build Debug APK: Compiles app|
| 4. Run Unit Tests: Checks errors|
|                              |
| [Save Workflow] [Cancel]      |
----------------------------------
User can scroll the YAML text if needed
Tapping 'Save Workflow' would save the workflow file (placeholder)
Tapping 'Cancel' would discard changes and close screen (placeholder)
Stretch Goal
Add a toggle switch to enable or disable automatic deployment after tests pass
💡 Hint
Use a Switch component and update the YAML content dynamically to include a deploy job when enabled

Practice

(1/5)
1. What is the main purpose of using GitHub Actions in an Android Kotlin project?
easy
A. To automate building and testing the app on code changes
B. To write Kotlin code faster
C. To manually deploy the app to users
D. To edit the AndroidManifest.xml file

Solution

  1. Step 1: Understand GitHub Actions role

    GitHub Actions automates tasks like building and testing when code changes.
  2. Step 2: Identify the main benefit

    This automation helps keep the app healthy without manual work.
  3. Final Answer:

    To automate building and testing the app on code changes -> Option A
  4. Quick Check:

    Automation = building and testing [OK]
Hint: GitHub Actions automates tasks on code changes [OK]
Common Mistakes:
  • Thinking it writes code automatically
  • Confusing manual deployment with automation
  • Assuming it edits app files directly
2. Which of the following is the correct way to specify a job that runs on Ubuntu in a GitHub Actions workflow YAML file?
easy
A. runs-on: ubuntu-latest
B. runs: ubuntu-latest
C. run-on: ubuntu-latest
D. runs_on: ubuntu-latest

Solution

  1. Step 1: Recall GitHub Actions syntax for runner

    The correct key is runs-on with a hyphen.
  2. Step 2: Match the correct option

    runs-on: ubuntu-latest uses runs-on: ubuntu-latest, which is valid syntax.
  3. Final Answer:

    runs-on: ubuntu-latest -> Option A
  4. Quick Check:

    Key is runs-on with hyphen [OK]
Hint: Remember: 'runs-on' uses a hyphen, not underscore or other [OK]
Common Mistakes:
  • Using underscore instead of hyphen
  • Using 'runs' or 'run-on' keys incorrectly
  • Confusing key names with similar words
3. Given this GitHub Actions step in a workflow:
steps:
  - name: Build Debug APK
    run: ./gradlew assembleDebug

What will this step do when the workflow runs?
medium
A. It deploys the app to the Google Play Store
B. It runs unit tests only
C. It cleans the project without building
D. It runs the Gradle command to build the debug version of the app

Solution

  1. Step 1: Understand the Gradle command

    ./gradlew assembleDebug builds the debug APK of the app.
  2. Step 2: Identify the step action

    The step runs this command, so it builds the debug version.
  3. Final Answer:

    It runs the Gradle command to build the debug version of the app -> Option D
  4. Quick Check:

    assembleDebug = build debug APK [OK]
Hint: assembleDebug builds debug APK, not tests or deploys [OK]
Common Mistakes:
  • Confusing assembleDebug with deploy commands
  • Thinking it runs tests only
  • Assuming it cleans the project
4. You wrote this GitHub Actions workflow snippet:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Build APK
        run: gradlew assembleDebug

Why might this workflow fail during the build step?
medium
A. Because 'actions/checkout@v2' is an invalid action
B. Because the command should be './gradlew assembleDebug' with './' prefix
C. Because 'runs-on' should be 'runs_on'
D. Because the job name 'build' is not allowed

Solution

  1. Step 1: Check the build command syntax

    The Gradle wrapper command needs './gradlew' to run the local script.
  2. Step 2: Identify the error cause

    Missing './' causes 'gradlew' not found error, failing the build step.
  3. Final Answer:

    Because the command should be './gradlew assembleDebug' with './' prefix -> Option B
  4. Quick Check:

    Use './gradlew' to run Gradle wrapper [OK]
Hint: Always prefix Gradle wrapper with './' in Linux runners [OK]
Common Mistakes:
  • Omitting './' before gradlew
  • Thinking action version is invalid
  • Misnaming 'runs-on' key
  • Assuming job names are restricted
5. You want your GitHub Actions workflow to run tests only when Kotlin source files change. Which trigger configuration correctly achieves this?
hard
A. on: schedule: - cron: '0 0 * * *'
B. on: push: branches: - main
C. on: push: paths: - '**/*.kt'
D. on: pull_request: paths-ignore: - '**/*.kt'

Solution

  1. Step 1: Understand GitHub Actions triggers

    The paths filter runs workflow only if matching files change.
  2. Step 2: Match trigger to Kotlin files

    on: push: paths: - '**/*.kt' triggers on push when any .kt file changes, which is correct.
  3. Final Answer:

    on: push: paths: - '**/*.kt' -> Option C
  4. Quick Check:

    Use 'paths' to trigger on specific file changes [OK]
Hint: Use 'paths' filter to run workflow on specific file changes [OK]
Common Mistakes:
  • Using 'paths-ignore' instead of 'paths'
  • Triggering on branch only, not file changes
  • Using schedule trigger for file changes
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard