<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rishi Vachhani</title>
    <description>The latest articles on DEV Community by Rishi Vachhani (@vachhanirishi).</description>
    <link>https://dev.to/vachhanirishi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2893335%2F3f675c91-a026-44da-9202-31b44b639616.png</url>
      <title>DEV Community: Rishi Vachhani</title>
      <link>https://dev.to/vachhanirishi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vachhanirishi"/>
    <language>en</language>
    <item>
      <title>Streamline Your Flutter Development: Complete CI/CD Pipeline with GitHub Actions and Google Play Store Deployment</title>
      <dc:creator>Rishi Vachhani</dc:creator>
      <pubDate>Sat, 30 Aug 2025 11:13:44 +0000</pubDate>
      <link>https://dev.to/vachhanirishi/streamline-your-flutter-development-complete-cicd-pipeline-with-github-actions-and-google-play-21fc</link>
      <guid>https://dev.to/vachhanirishi/streamline-your-flutter-development-complete-cicd-pipeline-with-github-actions-and-google-play-21fc</guid>
      <description>&lt;h1&gt;
  
  
  Streamline Your Flutter Development: Complete CI/CD Pipeline with GitHub Actions and Google Play Store Deployment
&lt;/h1&gt;

&lt;p&gt;As Flutter applications grow in complexity, manual building and deployment processes become time-consuming and error-prone. Implementing a robust CI/CD (Continuous Integration/Continuous Deployment) pipeline can dramatically improve your development workflow, reduce human errors, and ensure consistent releases.&lt;/p&gt;

&lt;p&gt;In this comprehensive guide, we'll walk through setting up an automated CI/CD pipeline using GitHub Actions that builds your Flutter app, runs tests, and deploys directly to the Google Play Store.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Setting up GitHub Actions for Flutter CI/CD&lt;/li&gt;
&lt;li&gt;Configuring automatic deployment to Google Play Store&lt;/li&gt;
&lt;li&gt;Best practices for managing secrets and sensitive data&lt;/li&gt;
&lt;li&gt;Real-world pipeline configuration with practical examples&lt;/li&gt;
&lt;li&gt;Common pitfalls and how to avoid them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we dive in, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Flutter application hosted on GitHub&lt;/li&gt;
&lt;li&gt;A Google Play Console developer account&lt;/li&gt;
&lt;li&gt;Basic understanding of YAML and GitHub Actions&lt;/li&gt;
&lt;li&gt;Android app signing key (we'll cover this)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Part 1: Understanding the CI/CD Pipeline
&lt;/h2&gt;

&lt;p&gt;Our pipeline will consist of three main stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Integration (CI)&lt;/strong&gt;: Code validation, testing, and building&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Deployment (CD)&lt;/strong&gt;: Automated deployment to Google Play Store&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Pipeline health and deployment status tracking&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 2: Setting Up Google Play Console
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Service Account
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Visit the &lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a new project or select an existing one&lt;/li&gt;
&lt;li&gt;Navigate to "IAM &amp;amp; Admin" → "Service Accounts"&lt;/li&gt;
&lt;li&gt;Click "Create Service Account"&lt;/li&gt;
&lt;li&gt;Fill in the service account details:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;flutter-ci-cd-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: &lt;code&gt;Service account for Flutter CI/CD pipeline&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Configure Play Console Access
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://play.google.com/console" rel="noopener noreferrer"&gt;Google Play Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to "Setup" → "API access"&lt;/li&gt;
&lt;li&gt;Link your Google Cloud project&lt;/li&gt;
&lt;li&gt;Grant access to your service account with these permissions:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Release manager&lt;/strong&gt;: For uploading and releasing apps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View app information&lt;/strong&gt;: For reading app metadata&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Generate Service Account Key
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In Google Cloud Console, go to your service account&lt;/li&gt;
&lt;li&gt;Click "Keys" → "Add Key" → "Create new key"&lt;/li&gt;
&lt;li&gt;Select "JSON" format&lt;/li&gt;
&lt;li&gt;Download the key file (keep it secure!)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 3: Android App Signing Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Generate Upload Key
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;keytool &lt;span class="nt"&gt;-genkey&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-keystore&lt;/span&gt; upload-keystore.jks &lt;span class="nt"&gt;-keyalg&lt;/span&gt; RSA &lt;span class="nt"&gt;-keysize&lt;/span&gt; 2048 &lt;span class="nt"&gt;-validity&lt;/span&gt; 10000 &lt;span class="nt"&gt;-alias&lt;/span&gt; upload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create key.properties
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;android/key.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;storePassword&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_keystore_password&lt;/span&gt;
&lt;span class="py"&gt;keyPassword&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;your_key_password&lt;/span&gt;
&lt;span class="py"&gt;keyAlias&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;upload&lt;/span&gt;
&lt;span class="py"&gt;storeFile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;upload-keystore.jks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure build.gradle
&lt;/h3&gt;

&lt;p&gt;Update &lt;code&gt;android/app/build.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add before android block&lt;/span&gt;
&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keystorePropertiesFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'key.properties'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keystorePropertiesFile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keystorePropertiesFile&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... existing configuration&lt;/span&gt;

    &lt;span class="n"&gt;signingConfigs&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;keyAlias&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'keyAlias'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;keyPassword&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'keyPassword'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;storeFile&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'storeFile'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'storeFile'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
            &lt;span class="n"&gt;storePassword&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'storePassword'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;buildTypes&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;signingConfig&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;release&lt;/span&gt;
            &lt;span class="n"&gt;minifyEnabled&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="n"&gt;proguardFiles&lt;/span&gt; &lt;span class="nf"&gt;getDefaultProguardFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'proguard-android.txt'&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'proguard-rules.pro'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 4: GitHub Actions CI/CD Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Complete Workflow Configuration
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/flutter-ci-cd.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Flutter CI/CD Pipeline&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;develop&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;published&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;FLUTTER_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.24.0"&lt;/span&gt;
  &lt;span class="na"&gt;JAVA_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;17"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Continuous Integration Job&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests and Analysis&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Java&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temurin'&lt;/span&gt;
        &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.JAVA_VERSION }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Flutter&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;flutter-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.FLUTTER_VERSION }}&lt;/span&gt;
        &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stable'&lt;/span&gt;
        &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify formatting&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dart format --output=none --set-exit-if-changed .&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Analyze project source&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter analyze --fatal-infos&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run unit tests&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter test --coverage&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload coverage to Codecov&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;codecov/codecov-action@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CODECOV_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coverage/lcov.info&lt;/span&gt;

  &lt;span class="c1"&gt;# Build Job&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build APK and App Bundle&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'push' || github.event_name == 'release'&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Java&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temurin'&lt;/span&gt;
        &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.JAVA_VERSION }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Flutter&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;flutter-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.FLUTTER_VERSION }}&lt;/span&gt;
        &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stable'&lt;/span&gt;
        &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Decode keystore&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode &amp;gt; android/app/keystore.jks&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create key.properties&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo "storeFile=keystore.jks" &amp;gt; android/key.properties&lt;/span&gt;
        &lt;span class="s"&gt;echo "storePassword=${{ secrets.KEYSTORE_PASSWORD }}" &amp;gt;&amp;gt; android/key.properties&lt;/span&gt;
        &lt;span class="s"&gt;echo "keyPassword=${{ secrets.KEY_PASSWORD }}" &amp;gt;&amp;gt; android/key.properties&lt;/span&gt;
        &lt;span class="s"&gt;echo "keyAlias=${{ secrets.KEY_ALIAS }}" &amp;gt;&amp;gt; android/key.properties&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build APK&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter build apk --release&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build App Bundle&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter build appbundle --release&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload APK artifact&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-apk&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/flutter-apk/app-release.apk&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload App Bundle artifact&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-aab&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/bundle/release/app-release.aab&lt;/span&gt;

  &lt;span class="c1"&gt;# Deploy to Google Play Store&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Play Store&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'release' &amp;amp;&amp;amp; github.event.action == 'published'&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download App Bundle artifact&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/download-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-aab&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create service account JSON&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo "${{ secrets.GOOGLE_SERVICES_JSON }}" | base64 --decode &amp;gt; service-account.json&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Play Store&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;r0adkll/upload-google-play@v1.1.3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;serviceAccountJson&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service-account.json&lt;/span&gt;
        &lt;span class="na"&gt;packageName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;com.yourcompany.yourapp&lt;/span&gt;
        &lt;span class="na"&gt;releaseFiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app-release.aab&lt;/span&gt;
        &lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;completed&lt;/span&gt;
        &lt;span class="na"&gt;inAppUpdatePriority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
        &lt;span class="na"&gt;userFraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5&lt;/span&gt;
        &lt;span class="na"&gt;whatsNewDirectory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;distribution/whatsnew&lt;/span&gt;
        &lt;span class="na"&gt;mappingFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/app/outputs/mapping/release/mapping.txt&lt;/span&gt;

  &lt;span class="c1"&gt;# Notify on deployment&lt;/span&gt;
  &lt;span class="na"&gt;notify&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send Deployment Notification&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always()&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Notify Slack&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;needs.deploy.result == 'success'&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8398a7/action-slack@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;success&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;🚀&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Flutter&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;successfully&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deployed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Play&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Store!'&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Notify on failure&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;needs.deploy.result == 'failure'&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8398a7/action-slack@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;❌&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Flutter&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failed!'&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 5: Advanced Pipeline Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multi-Environment Deployment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;internal&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;alpha&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal&lt;/span&gt;
        &lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal&lt;/span&gt;
        &lt;span class="na"&gt;user_fraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alpha&lt;/span&gt;
        &lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alpha&lt;/span&gt;
        &lt;span class="na"&gt;user_fraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
        &lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
        &lt;span class="na"&gt;user_fraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional Deployments
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Internal Track&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/develop'&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;r0adkll/upload-google-play@v1.1.3&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Production&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'release'&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;r0adkll/upload-google-play@v1.1.3&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 6: Security Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Managing Secrets Securely
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Required GitHub Secrets
&lt;/h4&gt;

&lt;p&gt;Navigate to your repository → Settings → Secrets and variables → Actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KEYSTORE_BASE64          # Base64 encoded keystore file
KEYSTORE_PASSWORD        # Keystore password
KEY_PASSWORD            # Key password
KEY_ALIAS               # Key alias
GOOGLE_SERVICES_JSON    # Base64 encoded service account JSON
CODECOV_TOKEN          # Optional: for code coverage
SLACK_WEBHOOK_URL      # Optional: for notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Encoding Files to Base64
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Encode keystore&lt;/span&gt;
&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; upload-keystore.jks | pbcopy

&lt;span class="c"&gt;# Encode service account JSON&lt;/span&gt;
&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; service-account.json | pbcopy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Environment-Specific Configurations
&lt;/h3&gt;

&lt;p&gt;Create separate secret sets for different environments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DEV_KEYSTORE_BASE64
STAGING_KEYSTORE_BASE64
PROD_KEYSTORE_BASE64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Secret Rotation Strategy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Rotate service account keys every 90 days&lt;/li&gt;
&lt;li&gt;Use time-limited access tokens when possible&lt;/li&gt;
&lt;li&gt;Implement secret scanning in your repository&lt;/li&gt;
&lt;li&gt;Never commit secrets to version control&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Access Control
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Restrict deployment to specific branches&lt;/span&gt;
&lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/main' &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;

&lt;span class="c1"&gt;# Require manual approval for production deployments&lt;/span&gt;
&lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://play.google.com/store/apps/details?id=com.yourcompany.yourapp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 7: Enhanced Pipeline Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Code Quality Gates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run custom lints&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter analyze --fatal-warnings&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check code coverage threshold&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;COVERAGE=$(flutter test --coverage | grep -o '[0-9]*\.[0-9]*%' | head -1 | sed 's/%//')&lt;/span&gt;
    &lt;span class="s"&gt;if (( $(echo "$COVERAGE &amp;lt; 80" | bc -l) )); then&lt;/span&gt;
      &lt;span class="s"&gt;echo "Coverage $COVERAGE% is below threshold of 80%"&lt;/span&gt;
      &lt;span class="s"&gt;exit 1&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dynamic Version Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update version&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;VERSION_CODE=${{ github.run_number }}&lt;/span&gt;
    &lt;span class="s"&gt;VERSION_NAME="${{ github.ref_name }}-${{ github.run_number }}"&lt;/span&gt;

    &lt;span class="s"&gt;# Update pubspec.yaml&lt;/span&gt;
    &lt;span class="s"&gt;sed -i "s/version: .*/version: $VERSION_NAME+$VERSION_CODE/" pubspec.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parallel Testing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;unit&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;widget&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;integration&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run ${{ matrix.test-type }} tests&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter test test/${{ matrix.test-type }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 8: Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Build Failures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Gradle build fails due to dependency conflicts&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Clean build cache&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;flutter clean&lt;/span&gt;
    &lt;span class="s"&gt;flutter pub get&lt;/span&gt;
    &lt;span class="s"&gt;cd android &amp;amp;&amp;amp; ./gradlew clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 2: Keystore Issues
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Keystore not found or invalid&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify keystore&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;if [ ! -f "android/app/keystore.jks" ]; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "Keystore file not found!"&lt;/span&gt;
      &lt;span class="s"&gt;exit 1&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;
    &lt;span class="s"&gt;keytool -list -keystore android/app/keystore.jks -storepass ${{ secrets.KEYSTORE_PASSWORD }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 3: Play Console Upload Failures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Service account lacks permissions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify service account has "Release Manager" role&lt;/li&gt;
&lt;li&gt;Ensure app is properly linked in Play Console&lt;/li&gt;
&lt;li&gt;Check track configuration (internal/alpha/beta/production)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Part 9: Monitoring and Notifications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Slack Integration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Notify deployment status&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8398a7/action-slack@v3&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ job.status }}&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;repo,message,commit,author,action,eventName,ref,workflow&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Email Notifications
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send email notification&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure()&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dawidd6/action-send-mail@v3&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;smtp.gmail.com&lt;/span&gt;
    &lt;span class="na"&gt;server_port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;465&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.EMAIL_USERNAME }}&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.EMAIL_PASSWORD }}&lt;/span&gt;
    &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🚨 Flutter CI/CD Pipeline Failed&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;The CI/CD pipeline for ${{ github.repository }} has failed.&lt;/span&gt;

      &lt;span class="s"&gt;Commit: ${{ github.sha }}&lt;/span&gt;
      &lt;span class="s"&gt;Branch: ${{ github.ref }}&lt;/span&gt;
      &lt;span class="s"&gt;Author: ${{ github.actor }}&lt;/span&gt;

      &lt;span class="s"&gt;Check the logs: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev-team@yourcompany.com&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ci-cd@yourcompany.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 10: Performance Optimization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Caching Strategy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache Flutter dependencies&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v4&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;~/.pub-cache&lt;/span&gt;
      &lt;span class="s"&gt;${{ runner.tool_cache }}/flutter&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }}&lt;/span&gt;
    &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;${{ runner.os }}-flutter-&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache Gradle dependencies&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v4&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;~/.gradle/caches&lt;/span&gt;
      &lt;span class="s"&gt;~/.gradle/wrapper&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build Optimization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Enable Gradle daemon&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;mkdir -p ~/.gradle&lt;/span&gt;
    &lt;span class="s"&gt;echo "org.gradle.daemon=true" &amp;gt;&amp;gt; ~/.gradle/gradle.properties&lt;/span&gt;
    &lt;span class="s"&gt;echo "org.gradle.parallel=true" &amp;gt;&amp;gt; ~/.gradle/gradle.properties&lt;/span&gt;
    &lt;span class="s"&gt;echo "org.gradle.configureondemand=true" &amp;gt;&amp;gt; ~/.gradle/gradle.properties&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 11: Advanced Security Measures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Secret Scanning
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;.github/workflows/security-scan.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security Scan&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;develop&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;secret-scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run TruffleHog OSS&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trufflesecurity/trufflehog@main&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
        &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
        &lt;span class="na"&gt;head&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Dependency Vulnerability Scanning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run dependency audit&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;flutter pub deps --json | dart run security_audit&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check for outdated packages&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub outdated --exit-if-outdated&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Code Signing Verification
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify app signing&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;jarsigner -verify -verbose -certs build/app/outputs/bundle/release/app-release.aab&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 12: Multi-Platform Support
&lt;/h2&gt;

&lt;h3&gt;
  
  
  iOS Deployment Extension
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;build-ios&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build iOS&lt;/span&gt;
  &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;macos-latest&lt;/span&gt;
  &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;

  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Flutter&lt;/span&gt;
    &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;subosito/flutter-action@v2&lt;/span&gt;
    &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;flutter-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.FLUTTER_VERSION }}&lt;/span&gt;
      &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stable'&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub get&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build iOS&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter build ios --release --no-codesign&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build IPA&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;cd ios&lt;/span&gt;
      &lt;span class="s"&gt;xcodebuild -workspace Runner.xcworkspace \&lt;/span&gt;
                 &lt;span class="s"&gt;-scheme Runner \&lt;/span&gt;
                 &lt;span class="s"&gt;-configuration Release \&lt;/span&gt;
                 &lt;span class="s"&gt;-destination generic/platform=iOS \&lt;/span&gt;
                 &lt;span class="s"&gt;-archivePath build/Runner.xcarchive \&lt;/span&gt;
                 &lt;span class="s"&gt;archive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Essential Resources and Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Google Play Console &amp;amp; APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://play.google.com/console" rel="noopener noreferrer"&gt;Google Play Console&lt;/a&gt; - Main dashboard for app management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud Console&lt;/a&gt; - Service account management&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/android-publisher" rel="noopener noreferrer"&gt;Google Play Developer API&lt;/a&gt; - API documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.google.com/googleplay/android-developer" rel="noopener noreferrer"&gt;Play Console Help&lt;/a&gt; - Official support docs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GitHub Actions Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace?type=actions" rel="noopener noreferrer"&gt;GitHub Actions Marketplace&lt;/a&gt; - Find reusable actions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace/actions/flutter-action" rel="noopener noreferrer"&gt;Flutter Action&lt;/a&gt; - Official Flutter setup action&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marketplace/actions/upload-android-release-to-play-store" rel="noopener noreferrer"&gt;Upload Google Play Action&lt;/a&gt; - Play Store deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/trufflesecurity/trufflehog" rel="noopener noreferrer"&gt;TruffleHog&lt;/a&gt; - Secret detection&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gitguardian.com/" rel="noopener noreferrer"&gt;GitGuardian&lt;/a&gt; - Secret monitoring service&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices Checklist
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Use GitHub Secrets for all sensitive data&lt;/li&gt;
&lt;li&gt;✅ Encode binary files (keystore, service account) as Base64&lt;/li&gt;
&lt;li&gt;✅ Implement secret rotation schedule&lt;/li&gt;
&lt;li&gt;✅ Enable branch protection rules&lt;/li&gt;
&lt;li&gt;✅ Use environment-specific deployments&lt;/li&gt;
&lt;li&gt;✅ Implement secret scanning&lt;/li&gt;
&lt;li&gt;✅ Never commit secrets to repository&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Cache Flutter and Gradle dependencies&lt;/li&gt;
&lt;li&gt;✅ Use matrix builds for parallel testing&lt;/li&gt;
&lt;li&gt;✅ Optimize Docker images if using containers&lt;/li&gt;
&lt;li&gt;✅ Implement incremental builds&lt;/li&gt;
&lt;li&gt;✅ Use artifact caching between jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reliability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Implement proper error handling&lt;/li&gt;
&lt;li&gt;✅ Add retry mechanisms for flaky operations&lt;/li&gt;
&lt;li&gt;✅ Use health checks before deployment&lt;/li&gt;
&lt;li&gt;✅ Implement rollback strategies&lt;/li&gt;
&lt;li&gt;✅ Monitor deployment success rates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code Quality
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Run automated tests (unit, widget, integration)&lt;/li&gt;
&lt;li&gt;✅ Enforce code formatting standards&lt;/li&gt;
&lt;li&gt;✅ Implement static analysis&lt;/li&gt;
&lt;li&gt;✅ Check code coverage thresholds&lt;/li&gt;
&lt;li&gt;✅ Scan for security vulnerabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Monitoring Your Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Key Metrics to Track
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build Success Rate&lt;/strong&gt;: Percentage of successful builds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Frequency&lt;/strong&gt;: How often you deploy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lead Time&lt;/strong&gt;: Time from commit to production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mean Time to Recovery&lt;/strong&gt;: Time to fix failed deployments&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting Up Monitoring
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Record metrics&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;echo "build_duration=${{ job.duration }}" &amp;gt;&amp;gt; metrics.log&lt;/span&gt;
    &lt;span class="s"&gt;echo "commit_sha=${{ github.sha }}" &amp;gt;&amp;gt; metrics.log&lt;/span&gt;
    &lt;span class="s"&gt;echo "deployment_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)" &amp;gt;&amp;gt; metrics.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Pitfalls and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Version Conflicts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Flutter/Dart version mismatches&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Pin specific versions in workflow and use version matrix for testing&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Keystore Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Keystore security and access&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Use Base64 encoding and GitHub Secrets, never commit keystore files&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Play Console Permissions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Service account lacks necessary permissions&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Grant "Release Manager" role and verify API access configuration&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Build Artifacts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Large artifact sizes affecting pipeline performance&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Implement artifact cleanup and use efficient compression&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Implementing a robust CI/CD pipeline for your Flutter application transforms your development workflow from manual, error-prone processes to automated, reliable deployments. This setup ensures that every code change is thoroughly tested, properly built, and securely deployed to the Google Play Store.&lt;/p&gt;

&lt;p&gt;Key benefits you'll experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster Release Cycles&lt;/strong&gt;: Automated processes reduce deployment time from hours to minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Code Quality&lt;/strong&gt;: Automated testing catches issues before they reach production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: Proper secret management and automated security scanning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Collaboration&lt;/strong&gt;: Standardized processes make team collaboration smoother&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Human Error&lt;/strong&gt;: Automation eliminates manual deployment mistakes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Implement the basic pipeline and test with a simple Flutter app&lt;/li&gt;
&lt;li&gt;Gradually add advanced features like multi-environment deployment&lt;/li&gt;
&lt;li&gt;Set up monitoring and alerting for pipeline health&lt;/li&gt;
&lt;li&gt;Establish a secret rotation schedule&lt;/li&gt;
&lt;li&gt;Document your team's deployment processes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember, CI/CD is an iterative process. Start simple, monitor your pipeline's performance, and continuously improve based on your team's needs and feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.flutter.dev/deployment/cd" rel="noopener noreferrer"&gt;Flutter DevOps Guide&lt;/a&gt; - Official Flutter deployment docs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.android.com/platform/technology/app-bundle" rel="noopener noreferrer"&gt;Android App Bundle Guide&lt;/a&gt; - Google's app bundle documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions Documentation&lt;/a&gt; - Complete GitHub Actions reference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding, and may your deployments be ever smooth! 🚀&lt;/p&gt;




</description>
      <category>cicd</category>
      <category>flutter</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>Setting Up Auto Scaling Groups and Load Balancer on AWS EC2: A Step-by Step Guide</title>
      <dc:creator>Rishi Vachhani</dc:creator>
      <pubDate>Sun, 27 Apr 2025 08:30:09 +0000</pubDate>
      <link>https://dev.to/vachhanirishi/setting-up-auto-scaling-groups-and-load-balancer-on-aws-ec2-a-step-by-step-guide-1io9</link>
      <guid>https://dev.to/vachhanirishi/setting-up-auto-scaling-groups-and-load-balancer-on-aws-ec2-a-step-by-step-guide-1io9</guid>
      <description>&lt;p&gt;Ensuring high availability and scalability for your application is crucial when deploying on AWS.&lt;/p&gt;

&lt;p&gt;In this guide, we'll walk through setting up Auto Scaling Groups (ASG), an Application Load Balancer (ALB), and a Target Group on AWS EC2.&lt;br&gt;
By the end, you'll have a fully functional architecture that dynamically scales based on demand.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Launch EC2 Instance
Before setting up Auto Scaling, start by launching an EC2 instance and configuring it to serve traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install Nginx on the Instance&lt;br&gt;
Once your instance is running, install an Nginx server to serve a default page:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install nginx -y&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;When you access the instance's public IP in a browser, you should see the default Nginx welcome page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Create a Target Group
A Target Group is needed to route traffic from the Load Balancer to the EC2 instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps to Create a Target Group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Target Groups in the AWS EC2 dashboard.&lt;/li&gt;
&lt;li&gt;Click Create Target Group.&lt;/li&gt;
&lt;li&gt;Select Instances as the target type.&lt;/li&gt;
&lt;li&gt;Specify the port (80/443) and protocol (HTTP/HTTPS).&lt;/li&gt;
&lt;li&gt;Attach the previously launched EC2 instances.&lt;/li&gt;
&lt;li&gt;AWS will now check the health status of the instances.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
Create an Application Load Balancer (ALB)
The Load Balancer distributes incoming traffic across multiple instances, improving availability and reliability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps to Create a Load Balancer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Load Balancers in the AWS dashboard.&lt;/li&gt;
&lt;li&gt;Click Create Load Balancer and select Application Load Balancer.&lt;/li&gt;
&lt;li&gt;Choose Internet-facing as the scheme.&lt;/li&gt;
&lt;li&gt;Configure Security Groups to allow HTTP/HTTPS traffic.&lt;/li&gt;
&lt;li&gt;Select Regions and Availability Zones as needed.&lt;/li&gt;
&lt;li&gt;Attach the previously created Target Group.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Click Create Load Balancer.&lt;/p&gt;

&lt;p&gt;Once created, you can access the instances using the Load Balancer's DNS name.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Create a Launch Template
A Launch Template defines the instance configuration for Auto Scaling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps to Create a Launch Template:&lt;/p&gt;

&lt;p&gt;Navigate to Launch Templates in AWS.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click Create Launch Template.&lt;/li&gt;
&lt;li&gt;Choose an instance type (e.g., t2.micro, t3.medium).&lt;/li&gt;
&lt;li&gt;Configure network settings and attach necessary storage.&lt;/li&gt;
&lt;li&gt;Select Security Groups and Key Pairs for authentication.&lt;/li&gt;
&lt;li&gt;Save and create the Launch Template.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
Set Up an Auto Scaling Group (ASG)
Auto Scaling ensures that your application scales up or down based on demand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps to Create an Auto Scaling Group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Auto Scaling Groups in AWS.&lt;/li&gt;
&lt;li&gt;Click Create Auto Scaling Group.&lt;/li&gt;
&lt;li&gt;Select the previously created Launch Template.&lt;/li&gt;
&lt;li&gt;Choose VPC settings and Subnets.&lt;/li&gt;
&lt;li&gt;Define the desired number of instances to maintain.&lt;/li&gt;
&lt;li&gt;Integrate with the Load Balancer and Target Group.&lt;/li&gt;
&lt;li&gt;Configure additional settings like Scaling Policies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Click Create Auto Scaling Group.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Configure Dynamic Scaling Policies
A Dynamic Scaling Policy adjusts the number of instances based on traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps to Configure Scaling Policies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Auto Scaling Groups.&lt;/li&gt;
&lt;li&gt;Select Scaling Policies.&lt;/li&gt;
&lt;li&gt;Define Scaling Conditions such as CPU utilization or request rate.&lt;/li&gt;
&lt;li&gt;Choose Step Scaling or Target Tracking Scaling.&lt;/li&gt;
&lt;li&gt;Set thresholds for scaling in and out dynamically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Save the policy — AWS will now adjust instances automatically based on demand.&lt;/p&gt;

&lt;p&gt;Final Architecture Overview&lt;br&gt;
After completing these steps, your AWS setup will include:&lt;/p&gt;

&lt;p&gt;✅ EC2 instances running Nginx&lt;br&gt;
✅ An Application Load Balancer distributing traffic&lt;br&gt;
✅ A Target Group managing instance health&lt;br&gt;
✅ An Auto Scaling Group ensuring dynamic scaling&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiybrln93j70k68ck057c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiybrln93j70k68ck057c.png" alt="Image description" width="761" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This architecture ensures high availability, fault tolerance, and scalability for your AWS-hosted applications.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;
By following this guide, you've successfully deployed a scalable and fault-tolerant AWS infrastructure using Auto Scaling, Load Balancer, and Target Groups.&lt;br&gt;
This setup ensures your application remains highly available even during traffic spikes.&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 For a detailed step-by-step guide with images, download the PDF &lt;a href="https://docs.google.com/document/d/1-gD4uwvILBT92iprmF9YxFN54twPXXtX/edit" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;👥 Thanks to &lt;a class="mentioned-user" href="https://dev.to/vikram_patel"&gt;@vikram_patel&lt;/a&gt;, &lt;a class="mentioned-user" href="https://dev.to/shreyansh_1904"&gt;@shreyansh_1904&lt;/a&gt;, &lt;a class="mentioned-user" href="https://dev.to/karmpatel"&gt;@karmpatel&lt;/a&gt;, and &lt;a class="mentioned-user" href="https://dev.to/thisaakash"&gt;@thisaakash&lt;/a&gt; for their collaboration.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Automating CPU and Memory Utilization Logging with Cron Jobs on Windows and Linux</title>
      <dc:creator>Rishi Vachhani</dc:creator>
      <pubDate>Fri, 14 Mar 2025 16:08:58 +0000</pubDate>
      <link>https://dev.to/vachhanirishi/automating-cpu-and-memory-utilization-logging-with-cron-jobs-on-windows-and-linux-2phl</link>
      <guid>https://dev.to/vachhanirishi/automating-cpu-and-memory-utilization-logging-with-cron-jobs-on-windows-and-linux-2phl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Monitoring system performance is crucial for maintaining a healthy and efficient computing environment. In this guide, we will automate the logging of CPU and memory utilization every 15 minutes using scheduled tasks in Windows and cron jobs in Linux. We will also ensure that a new log file is created daily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This is Useful in Everyday Life
&lt;/h2&gt;

&lt;p&gt;Automating system monitoring can greatly simplify daily operations, especially for developers, system administrators, and IT professionals. Instead of manually checking system resource usage, automated logging allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Early detection of performance issues&lt;/strong&gt; – Identify spikes in CPU or memory usage before they cause major slowdowns or crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient troubleshooting&lt;/strong&gt; – Logs provide historical data, making it easier to diagnose and resolve performance problems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better resource planning&lt;/strong&gt; – Analyze usage trends over time to optimize system resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Peace of mind&lt;/strong&gt; – Once set up, the script runs in the background without user intervention, ensuring continuous monitoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up the Python Script
&lt;/h2&gt;

&lt;p&gt;Before setting up the scheduled jobs, let's create a Python script that logs CPU and memory utilization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Required Dependencies
&lt;/h3&gt;

&lt;p&gt;We will use the &lt;code&gt;psutil&lt;/code&gt; module to fetch CPU and memory utilization. If you haven't installed it yet, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;psutil
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Python Script to Log System Utilization
&lt;/h3&gt;

&lt;p&gt;Create a script named &lt;code&gt;system_monitor.py&lt;/code&gt; with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_system_utilization&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu_memory_log_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d %H:%M:%S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cpu_usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpu_percent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;memory_usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;virtual_memory&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;percent&lt;/span&gt;
        &lt;span class="n"&gt;log_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - CPU Usage: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cpu_usage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;% | Memory Usage: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;memory_usage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;log_system_utilization&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a log directory if it doesn’t exist.&lt;/li&gt;
&lt;li&gt;Generates a new log file daily.&lt;/li&gt;
&lt;li&gt;Logs CPU and memory usage every time it runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scheduling the Script on Linux Using Cron Job
&lt;/h2&gt;

&lt;p&gt;In Linux, we use cron jobs to automate script execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Open the Crontab Editor
&lt;/h3&gt;

&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Add the Cron Job
&lt;/h3&gt;

&lt;p&gt;Add the following line at the end of the file to run the script every 15 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt;/15 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /usr/bin/python3 /path/to/system_monitor.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;*/15&lt;/code&gt; → Runs every 15 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;* * * *&lt;/code&gt; → Runs every hour, day, month, and weekday.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/usr/bin/python3&lt;/code&gt; → Path to the Python interpreter.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/path/to/system_monitor.py&lt;/code&gt; → Full path to the script.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Save and Exit
&lt;/h3&gt;

&lt;p&gt;Save the file and exit. The cron job will now run every 15 minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Verify the Cron Job
&lt;/h3&gt;

&lt;p&gt;To list scheduled cron jobs, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;crontab &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scheduling the Script on Windows Using Task Scheduler
&lt;/h2&gt;

&lt;p&gt;On Windows, we use Task Scheduler to automate the script execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Open Task Scheduler
&lt;/h3&gt;

&lt;p&gt;Press &lt;code&gt;Win + R&lt;/code&gt;, type &lt;code&gt;taskschd.msc&lt;/code&gt;, and hit Enter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a New Task
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Create Basic Task&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Name it "System Utilization Logger" and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Set the Trigger
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Choose &lt;strong&gt;Daily&lt;/strong&gt; and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set the start time to midnight and repeat every day.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Set the Action
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Choose &lt;strong&gt;Start a Program&lt;/strong&gt; and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Browse to the Python executable (e.g., &lt;code&gt;C:\Python39\python.exe&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;Add arguments&lt;/strong&gt; field, enter the full path to &lt;code&gt;system_monitor.py&lt;/code&gt;, e.g.:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   "C:\path\to\system_monitor.py"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt; and then &lt;strong&gt;Finish&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 5: Modify Task to Run Every 15 Minutes
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Task Scheduler Library&lt;/strong&gt;, right-click the created task, and select &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Go to the &lt;strong&gt;Triggers&lt;/strong&gt; tab and click &lt;strong&gt;Edit&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Repeat task every 15 minutes&lt;/strong&gt; and &lt;strong&gt;Stop after 1 day&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;OK&lt;/strong&gt; and &lt;strong&gt;Apply&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 6: Test the Task
&lt;/h3&gt;

&lt;p&gt;Right-click the task and select &lt;strong&gt;Run&lt;/strong&gt; to ensure it executes correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following this guide, you've successfully automated system monitoring on both Linux and Windows. The script now runs every 15 minutes, generating daily logs to track CPU and memory utilization. This setup helps in proactive system monitoring and can be further enhanced with alert mechanisms or cloud storage integrations.&lt;/p&gt;

&lt;h3&gt;
  
  
  How This Makes Life Easier
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Saves Time &amp;amp; Effort:&lt;/strong&gt; No need to manually check system performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improves System Stability:&lt;/strong&gt; Prevent unexpected failures by analyzing logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhances Troubleshooting:&lt;/strong&gt; Quickly identify patterns of high CPU/memory usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable &amp;amp; Automated:&lt;/strong&gt; Works on any system without manual intervention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this setup in place, you can focus on other important tasks while ensuring your system's performance is continuously monitored. 🚀&lt;/p&gt;

&lt;p&gt;Let me know in the comments if you have any questions or suggestions!&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/vikram_patel"&gt;@vikram_patel&lt;/a&gt; , &lt;a class="mentioned-user" href="https://dev.to/thisaakash"&gt;@thisaakash&lt;/a&gt; , &lt;a class="mentioned-user" href="https://dev.to/shreyansh_1904"&gt;@shreyansh_1904&lt;/a&gt;, &lt;a class="mentioned-user" href="https://dev.to/karmpatel"&gt;@karmpatel&lt;/a&gt; Thanks for colloborations.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>systemmonitoring</category>
      <category>performanceoptimization</category>
      <category>techtips</category>
    </item>
    <item>
      <title>Understanding Runlevels in Linux: A Complete Guide</title>
      <dc:creator>Rishi Vachhani</dc:creator>
      <pubDate>Sat, 08 Mar 2025 05:42:08 +0000</pubDate>
      <link>https://dev.to/vachhanirishi/understanding-runlevels-in-linux-a-complete-guide-2pbp</link>
      <guid>https://dev.to/vachhanirishi/understanding-runlevels-in-linux-a-complete-guide-2pbp</guid>
      <description>&lt;p&gt;Linux is a powerful and flexible operating system used in servers, embedded systems, and desktops worldwide. One of the essential components of Linux system administration is &lt;strong&gt;runlevels&lt;/strong&gt;. Runlevels define the state of a Linux system by controlling the services and processes that run at startup.&lt;/p&gt;

&lt;p&gt;Whether you’re troubleshooting boot issues or managing system services, understanding runlevels can significantly improve your Linux administration skills. In this blog, we’ll explore &lt;strong&gt;what runlevels are, where they are used, how to check the current runlevel, how to change it, and real-world use cases&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Runlevels in Linux?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;runlevel&lt;/strong&gt; in Linux is a mode of operation that determines what processes and services are active at a given time. Different runlevels are predefined for various system states, such as &lt;strong&gt;single-user mode, multi-user mode, or GUI mode&lt;/strong&gt;. Traditionally, runlevels range from &lt;strong&gt;0 to 6&lt;/strong&gt;, each serving a specific purpose.&lt;/p&gt;




&lt;h2&gt;
  
  
  Standard Runlevels in Linux
&lt;/h2&gt;

&lt;p&gt;The standard runlevels in &lt;strong&gt;SysVinit-based&lt;/strong&gt; Linux distributions are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runlevel&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Halt (Shutdown)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Single-user mode (Maintenance Mode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Multi-user mode without network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Full multi-user mode (CLI)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Unused (customizable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Multi-user mode with GUI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Reboot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;However, modern Linux distributions such as &lt;strong&gt;Ubuntu (16.04+), RHEL 7+, and CentOS 7+&lt;/strong&gt; have replaced &lt;strong&gt;SysVinit&lt;/strong&gt; with &lt;strong&gt;systemd&lt;/strong&gt;, where &lt;strong&gt;targets&lt;/strong&gt; are used instead of runlevels.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Are Runlevels Used?
&lt;/h2&gt;

&lt;p&gt;Runlevels are used in various scenarios, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System Boot Management&lt;/strong&gt; — Define what services should start during boot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Troubleshooting&lt;/strong&gt; — Switching to &lt;strong&gt;single-user mode (Runlevel 1)&lt;/strong&gt; helps in fixing critical system issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Configurations&lt;/strong&gt; — Servers often run in &lt;strong&gt;Runlevel 3 (CLI mode)&lt;/strong&gt; to save resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GUI vs CLI Switching&lt;/strong&gt; — Users can switch between &lt;strong&gt;GUI (Runlevel 5)&lt;/strong&gt; and &lt;strong&gt;CLI (Runlevel 3)&lt;/strong&gt; as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom System Modes&lt;/strong&gt; — &lt;strong&gt;Runlevel 4&lt;/strong&gt; (unused by default) can be customized for specific requirements.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Check the Current Runlevel?
&lt;/h2&gt;

&lt;p&gt;To check the current runlevel of your Linux system, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;runlevel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Output:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;N 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;N&lt;/code&gt; indicates there was no previous runlevel change, and &lt;code&gt;5&lt;/code&gt; represents the current runlevel (multi-user mode with GUI).&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;systemd-based distributions&lt;/strong&gt;, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl get-default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Output:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;graphical.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This corresponds to &lt;strong&gt;Runlevel 5&lt;/strong&gt; in &lt;strong&gt;SysVinit&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Change Runlevels in Linux?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  In SysVinit-based Systems
&lt;/h3&gt;

&lt;p&gt;To switch to a different runlevel &lt;strong&gt;temporarily&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;init &amp;lt;runlevel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, to switch to runlevel 3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;init 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;telinit 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To &lt;strong&gt;change the default runlevel permanently&lt;/strong&gt;, edit the &lt;code&gt;/etc/inittab&lt;/code&gt; file and modify this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;default:5:initdefault:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;5&lt;/code&gt; to your desired runlevel and &lt;strong&gt;reboot&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  In Systemd-based Systems
&lt;/h3&gt;

&lt;p&gt;To &lt;strong&gt;change the current runlevel (target)&lt;/strong&gt; in &lt;strong&gt;systemd-based systems&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl isolate multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To &lt;strong&gt;set a default runlevel (target)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl set-default multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To &lt;strong&gt;switch back to GUI mode&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl isolate graphical.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-Time Use Cases of Runlevels
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recovering a Broken System&lt;/strong&gt; — Boot into &lt;strong&gt;single-user mode (Runlevel 1)&lt;/strong&gt; to fix misconfigured files or disk errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running a Server Efficiently&lt;/strong&gt; — Use &lt;strong&gt;Runlevel 3 (multi-user CLI mode)&lt;/strong&gt; to optimize performance by disabling GUI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switching to Maintenance Mode&lt;/strong&gt; — If you need to perform updates or maintenance, temporarily move to &lt;strong&gt;Runlevel 1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Troubleshooting Network Issues&lt;/strong&gt; — &lt;strong&gt;Runlevel 2 (no network)&lt;/strong&gt; helps isolate networking problems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automating Startup Services&lt;/strong&gt; — Customize runlevel scripts for specific startup configurations.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Understanding &lt;strong&gt;Linux runlevels&lt;/strong&gt; is crucial for &lt;strong&gt;system administrators and advanced users&lt;/strong&gt;. Whether you’re using an old &lt;strong&gt;SysVinit-based system&lt;/strong&gt; or a modern &lt;strong&gt;systemd-based one&lt;/strong&gt;, knowing how to &lt;strong&gt;check, change, and utilize runlevels&lt;/strong&gt; can improve system management.&lt;/p&gt;

&lt;p&gt;By mastering runlevels, you can &lt;strong&gt;efficiently manage services, troubleshoot issues, and optimize system performance&lt;/strong&gt;. Start experimenting with different runlevels today to enhance your Linux skills!&lt;/p&gt;




&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/vikram_patel"&gt;@vikram_patel&lt;/a&gt;, &lt;a class="mentioned-user" href="https://dev.to/thisaakash"&gt;@thisaakash&lt;/a&gt; , &lt;a class="mentioned-user" href="https://dev.to/shreyansh_1904"&gt;@shreyansh_1904&lt;/a&gt; Thanks for colloborations.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sysadmins</category>
      <category>opensource</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Git Reset: Understanding and Using It Effectively</title>
      <dc:creator>Rishi Vachhani</dc:creator>
      <pubDate>Thu, 06 Mar 2025 16:14:34 +0000</pubDate>
      <link>https://dev.to/vachhanirishi/git-reset-understanding-and-using-it-effectively-4ja2</link>
      <guid>https://dev.to/vachhanirishi/git-reset-understanding-and-using-it-effectively-4ja2</guid>
      <description>&lt;p&gt;Git is a powerful Distributed Version Control System (DVCS) packed with commands that let developers manage their codebases efficiently. With its robust capabilities, Git provides flexibility for high-level operations while giving full access to its internals. It is fast, scalable, and an indispensable tool for modern development workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Git Reset?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git reset&lt;/code&gt; is one of Git’s most versatile yet often misunderstood commands. It allows developers to undo changes at different levels of their repository. Depending on the options provided (&lt;code&gt;--soft&lt;/code&gt;, &lt;code&gt;--mixed&lt;/code&gt;, &lt;code&gt;--hard&lt;/code&gt;), it manipulates three key components of Git:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commit Tree (HEAD):&lt;/strong&gt; Tracks the latest commit in the current branch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Staging Index:&lt;/strong&gt; Where changes are prepared for a commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Working Directory:&lt;/strong&gt; Reflects local files and modifications.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each mode of &lt;code&gt;git reset&lt;/code&gt; changes these components in different ways.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Modes of Git Reset
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Soft Reset (&lt;code&gt;git reset --soft&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Moves the &lt;code&gt;HEAD&lt;/code&gt; pointer to the specified commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keeps all changes in the staging area and working directory untouched.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; When you want to modify or amend a commit without losing your staged changes.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git reset &lt;span class="nt"&gt;--soft&lt;/span&gt; &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Mixed Reset (&lt;code&gt;git reset --mixed&lt;/code&gt;) (default)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Moves the &lt;code&gt;HEAD&lt;/code&gt; pointer to the specified commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unstages changes but retains them in the working directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; When you need to re-stage or redo your commit preparation.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git reset &lt;span class="nt"&gt;--mixed&lt;/span&gt; &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Hard Reset (&lt;code&gt;git reset --hard&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Moves the &lt;code&gt;HEAD&lt;/code&gt; pointer to the specified commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deletes all changes from both the staging area and the working directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; When you want to discard all changes and return to a clean state.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How Git Reset Works Internally
&lt;/h2&gt;

&lt;p&gt;To understand how &lt;code&gt;git reset&lt;/code&gt; works, let’s look at the three core components of a Git repository:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HEAD:&lt;/strong&gt; Points to the latest commit in the current branch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Index:&lt;/strong&gt; The staging area for changes ready to be committed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Working Directory:&lt;/strong&gt; The local files and their current state.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Use Cases for Git Reset
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;--soft&lt;/code&gt; for minor adjustments:&lt;/strong&gt; Great for tweaking or amending recent commits without losing any work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stick to &lt;code&gt;--mixed&lt;/code&gt; for safe resets:&lt;/strong&gt; Less destructive since it preserves changes in the working directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be cautious with &lt;code&gt;--hard&lt;/code&gt;:&lt;/strong&gt; Only use it when you are sure you no longer need the uncommitted changes. Back up your work if necessary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid &lt;code&gt;git reset&lt;/code&gt; on shared branches:&lt;/strong&gt; Resetting history on shared branches can cause conflicts and confusion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leverage &lt;code&gt;git reflog&lt;/code&gt; for recovery:&lt;/strong&gt; If you reset to the wrong commit, &lt;code&gt;git reflog&lt;/code&gt; can help you recover lost references.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6l4o6lnc0oxldgxwibr7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6l4o6lnc0oxldgxwibr7.jpeg" alt="Work flow of Git reset" width="700" height="408"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Understanding &lt;code&gt;git reset&lt;/code&gt; is essential for managing code efficiently. Whether making small corrections, undoing staged changes, or completely resetting a repository, knowing when and how to use &lt;code&gt;git reset&lt;/code&gt; ensures a smooth development workflow.&lt;/p&gt;

&lt;p&gt;By mastering &lt;code&gt;git reset&lt;/code&gt;, developers can confidently navigate version history, fix mistakes, and optimize their Git experience.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/vikram_patel"&gt;@vikram_patel&lt;/a&gt; , &lt;a class="mentioned-user" href="https://dev.to/thisaakash"&gt;@thisaakash&lt;/a&gt; , &lt;a class="mentioned-user" href="https://dev.to/shreyansh_1904"&gt;@shreyansh_1904&lt;/a&gt; Thanks for collaborations.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>github</category>
      <category>development</category>
      <category>git</category>
    </item>
  </channel>
</rss>
