Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
66355a3
feat: implement unified build system
MohamadJaara Jun 11, 2025
3d0b84a
chore: reorder temporary mockative repository in build.gradle.kts
MohamadJaara Jun 11, 2025
cfe2c0e
feat: update build configuration to remove Staging flavor and add key…
MohamadJaara Jun 11, 2025
624e304
feat: update artifact download name to include build flavor and variant
MohamadJaara Jun 11, 2025
e043798
feat: normalize build flavor and variant inputs to lowercase
MohamadJaara Jun 11, 2025
554f5f7
feat: enhance quality gates and build process with detailed summaries
MohamadJaara Jun 12, 2025
07925bd
Update .github/workflows/build-unified.yml
MohamadJaara Jul 4, 2025
8f9c0d2
Update .github/workflows/build-unified.yml
MohamadJaara Jul 4, 2025
e164fa4
Merge branch 'develop' into mo/feat/improved-pipeline
MohamadJaara Jul 4, 2025
d5cb966
Merge branch 'develop' into mo/feat/improved-pipeline
MohamadJaara Jul 7, 2025
7bd02fe
trigger CI/CD
MohamadJaara Jul 7, 2025
0c254a6
refactor: remove unused build configuration for Internal flavor and i…
MohamadJaara Jul 7, 2025
da06b88
Merge branch 'develop' into mo/feat/improved-pipeline
MohamadJaara Jul 7, 2025
f4eb08e
refactor: simplify workflow names by removing "Unified" suffix
MohamadJaara Jul 7, 2025
fc997b3
refactor: improve CI pipeline by inlining quality checks and simplify…
MohamadJaara Jul 7, 2025
783adfd
feat: add CI workflows for develop and main branches with deployment …
MohamadJaara Jul 7, 2025
7ab9e07
refactor: update Gradle wrapper validation action to the latest version
MohamadJaara Jul 7, 2025
13e1933
refactor: update deployment-targets format to use structured JSON arrays
MohamadJaara Jul 7, 2025
097a975
feat: add permissions configuration to workflow files for improved ac…
MohamadJaara Jul 7, 2025
e026895
feat: update PR author assignment and semantic commit linting to use …
MohamadJaara Jul 7, 2025
68bf7df
ci: improve keystore handling and security
MohamadJaara Jul 8, 2025
cec20fa
Merge branch 'develop' into mo/feat/improved-pipeline
MohamadJaara Jul 8, 2025
50cc20e
Merge branch 'develop' into mo/feat/improved-pipeline
MohamadJaara Jul 18, 2025
360eabc
trigger CI/CD
MohamadJaara Jul 18, 2025
9fd6449
fix: update deployment-targets format to use array syntax in build YA…
MohamadJaara Jul 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .github/actions/setup-keystore/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: 'Setup Keystore'
description: 'Decode and setup keystore for signing Android builds'

inputs:
keystore-type:
description: 'Type of keystore to setup (debug|prerelease|internal|public)'
required: true
keystore-path:
description: 'Path where keystore should be placed'
required: false
default: '${{ runner.temp }}/keystore'

outputs:
keystore-file-path:
description: 'Full path to the decoded keystore file'
value: ${{ steps.setup.outputs.keystore-file-path }}

runs:
using: 'composite'
steps:
- name: Validate keystore type
shell: bash
run: |
case "${{ inputs.keystore-type }}" in
debug|prerelease|internal|public)
echo "Valid keystore type: ${{ inputs.keystore-type }}"
;;
*)
echo "Error: Invalid keystore type '${{ inputs.keystore-type }}'. Must be one of: debug, prerelease, internal, public"
exit 1
;;
esac

- name: Setup keystore directory
shell: bash
run: |
mkdir -p "${{ inputs.keystore-path }}"

- name: Decode keystore
id: setup
shell: bash
env:
KEYSTORE_TYPE: ${{ inputs.keystore-type }}
KEYSTORE_PATH: ${{ inputs.keystore-path }}
run: |
# Map keystore type to secret name
case "${KEYSTORE_TYPE}" in
debug)
SECRET_NAME="ENCODED_KEYSTORE_DEBUG"
;;
prerelease)
SECRET_NAME="ENCODED_KEYSTORE_PRE_RELEASE"
;;
internal)
SECRET_NAME="ENCODED_KEYSTORE_INTERNAL_RELEASE"
;;
public)
SECRET_NAME="ENCODED_KEYSTORE_PUBLIC_RELEASE"
;;
esac

# Get the encoded keystore from environment
ENCODED_KEYSTORE=$(printenv "${SECRET_NAME}" || echo "")

if [ -z "${ENCODED_KEYSTORE}" ]; then
echo "Error: Secret ${SECRET_NAME} not found or empty"
exit 1
fi

# Decode keystore to file
KEYSTORE_FILE="${KEYSTORE_PATH}/the.keystore"
echo "${ENCODED_KEYSTORE}" | base64 -d > "${KEYSTORE_FILE}"

# Verify file was created
if [ ! -f "${KEYSTORE_FILE}" ]; then
echo "Error: Failed to create keystore file"
exit 1
fi

echo "Keystore decoded successfully to: ${KEYSTORE_FILE}"
echo "keystore-file-path=${KEYSTORE_FILE}" >> $GITHUB_OUTPUT

- name: Set keystore environment variables
shell: bash
env:
KEYSTORE_TYPE: ${{ inputs.keystore-type }}
KEYSTORE_FILE_PATH: ${{ steps.setup.outputs.keystore-file-path }}
run: |
# Set common environment variables
echo "KEYSTORE_FILE_PATH_DEBUG=${KEYSTORE_FILE_PATH}" >> $GITHUB_ENV
echo "KEYSTORE_FILE_PATH_RELEASE=${KEYSTORE_FILE_PATH}" >> $GITHUB_ENV
echo "KEYSTORE_FILE_PATH_COMPAT=${KEYSTORE_FILE_PATH}" >> $GITHUB_ENV
echo "KEYSTORE_FILE_PATH_COMPAT_RELEASE=${KEYSTORE_FILE_PATH}" >> $GITHUB_ENV

# Set type-specific alias and password environment variables
case "${KEYSTORE_TYPE}" in
debug)
echo "Using debug keystore configuration"
# Debug keystore env vars will be set by secrets in calling workflow
;;
prerelease)
echo "Using pre-release keystore configuration"
# Pre-release keystore env vars will be set by secrets in calling workflow
;;
internal)
echo "Using internal release keystore configuration"
# Internal keystore env vars will be set by secrets in calling workflow
;;
public)
echo "Using public release keystore configuration"
# Public keystore env vars will be set by secrets in calling workflow
;;
esac
72 changes: 72 additions & 0 deletions .github/workflows/build-develop-unified.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: "Develop build (Unified)"

on:
push:
branches:
- develop
merge_group:
types: [ checks_requested ]
branches: [ develop ]
pull_request:
branches:
- develop
types: [ opened, synchronize ]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.merge_group.head_sha }}
cancel-in-progress: true

jobs:
# Build for PR and merge group validation (no store deployment)
build-validation:
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Dev",
"variant": "Debug",
"keystore-type": "debug",
"build-type": "apk",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}]"
},
{
"flavor": "Internal",
"variant": "Compat",
"keystore-type": "internal",
"build-type": "bundle",
"generate-version-file": false,
"deployment-targets": "[]"
}
]
enable-deployment: true
secrets: inherit

# Build for direct pushes to develop (includes internal store deployment)
build-develop:
if: github.event_name == 'push' && github.ref_name == 'develop'
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Dev",
"variant": "Debug",
"keystore-type": "debug",
"build-type": "apk",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}]"
},
{
"flavor": "Internal",
"variant": "Compat",
"keystore-type": "internal",
"build-type": "bundle",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}, {\"type\": \"google-play\", \"package-name\": \"com.wire.internal\", \"track\": \"internal\", \"status\": \"completed\"}]"
}
]
enable-deployment: true
secrets: inherit
53 changes: 53 additions & 0 deletions .github/workflows/build-main-unified.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: "Main build (Unified)"

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_call:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
validate-trigger:
runs-on: ubuntu-latest
outputs:
should-build: ${{ steps.check.outputs.should-build }}
steps:
- name: Check if should build
id: check
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
echo "Pull request detected - skipping build"
echo "should-build=false" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" != "refs/heads/main" ]]; then
echo "Not main branch - skipping build"
echo "should-build=false" >> $GITHUB_OUTPUT
else
echo "Push to main branch - proceeding with build"
echo "should-build=true" >> $GITHUB_OUTPUT
fi

build-beta:
needs: validate-trigger
if: needs.validate-trigger.outputs.should-build == 'true'
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Beta",
"variant": "Release",
"keystore-type": "prerelease",
"build-type": "both",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}, {\"type\": \"google-play\", \"package-name\": \"com.wire.android.internal\", \"track\": \"internal\"}]"
}
]
enable-deployment: true
secrets: inherit
69 changes: 69 additions & 0 deletions .github/workflows/build-production-unified.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: "Production build (Unified)"

on:
release:
types: [ published ]

concurrency:
group: ${{ github.workflow }}-${{ github.event.release.tag_name }}
cancel-in-progress: true

jobs:
validate-release:
runs-on: ubuntu-latest
steps:
- name: Get latest release tag
id: get_latest_release
run: |
latest_tag=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.tag_name')
echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT

- name: Compare versions
run: |
current_tag="${{ github.event.release.tag_name }}"
latest_tag="${{ steps.get_latest_release.outputs.latest_tag }}"
cur_ver="${current_tag#v}"
lat_ver="${latest_tag#v}"
highest="$(printf '%s\n%s' "$cur_ver" "$lat_ver" | sort -V | tail -n1)"
if [[ "$cur_ver" != "$lat_ver" && "$highest" != "$cur_ver" ]]; then
echo "Current tag ($current_tag) is lower than latest tag ($latest_tag). Failing the workflow."
exit 1
else
echo "Current tag ($current_tag) is equal or higher than $latest_tag. Continuing the workflow."
fi

build-production:
needs: validate-release
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Prod",
"variant": "Compatrelease",
"keystore-type": "public",
"build-type": "both",
"generate-version-file": true,
"deployment-targets": "[{\"type\": \"s3\"}, {\"type\": \"google-play\", \"package-name\": \"com.wire\", \"track\": \"alpha\"}, {\"type\": \"github-release\", \"additional-files\": \"app/version.txt\"}]"
}
]
enable-deployment: true
secrets: inherit

build-fdroid:
needs: validate-release
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Fdroid",
"variant": "Compatrelease",
"keystore-type": "public",
"build-type": "apk",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}, {\"type\": \"github-release\"}]"
}
]
enable-deployment: true
secrets: inherit
64 changes: 64 additions & 0 deletions .github/workflows/build-release-candidate-unified.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: "Release Candidate build (Unified)"

on:
push:
branches:
- release/candidate
merge_group:
types: [ checks_requested ]
branches: [ release/candidate ]
pull_request:
branches:
- release/candidate
types: [ opened, synchronize ]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.merge_group.head_sha }}
cancel-in-progress: true

jobs:
# Build for PR and merge group validation
build-validation:
if: github.event_name == 'merge_group' || (github.event.pull_request.head.repo.full_name == github.repository && github.event_name == 'pull_request')
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Staging",
"variant": "Compat",
"keystore-type": "internal",
"build-type": "apk",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}]"
}
]
enable-deployment: true
secrets: inherit

# Build for direct pushes to release/candidate
build-release-candidate:
if: github.event_name == 'push' && github.ref_name == 'release/candidate'
uses: ./.github/workflows/build-unified.yml
with:
build-config: |
[
{
"flavor": "Staging",
"variant": "Compat",
"keystore-type": "internal",
"build-type": "apk",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}]"
},
{
"flavor": "Internal",
"variant": "Compat",
"keystore-type": "internal",
"build-type": "both",
"generate-version-file": false,
"deployment-targets": "[{\"type\": \"s3\"}, {\"type\": \"google-play\", \"package-name\": \"com.wire.internal\", \"track\": \"production\", \"status\": \"completed\"}]"
}
]
enable-deployment: true
secrets: inherit
Loading