Remove invalid logo.synthfinance.com URLs from merchants table (#553) #150
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Reference: https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners | |
| # Conditions for pushing the image to GHCR: | |
| # - Triggered by push to default branch (`main`) | |
| # - Triggered by push to a version tag (`v*`) | |
| # - Triggered by a scheduled run | |
| # - Triggered manually via `workflow_dispatch` with `push: true` | |
| # | |
| # Conditional expression: | |
| # github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push | |
| name: Publish Docker image | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: 'Git ref (tag or commit SHA) to build' | |
| required: true | |
| type: string | |
| default: 'main' | |
| push: | |
| description: 'Push the image to container registry' | |
| required: false | |
| type: boolean | |
| default: false | |
| push: | |
| tags: | |
| - 'v*' | |
| branches: | |
| - main | |
| paths-ignore: | |
| - 'charts/**' | |
| schedule: | |
| - cron: '30 1 * * *' | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| permissions: | |
| contents: write | |
| packages: write | |
| jobs: | |
| ci: | |
| uses: ./.github/workflows/ci.yml | |
| build: | |
| name: Build Docker image | |
| needs: [ ci ] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: [amd64, arm64] | |
| timeout-minutes: 60 | |
| runs-on: ${{ matrix.platform == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} | |
| outputs: | |
| tags: ${{ steps.meta.outputs.tags }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Check out the repo | |
| uses: actions/[email protected] | |
| with: | |
| ref: ${{ github.event.inputs.ref || github.ref }} | |
| - name: Set up Docker Buildx | |
| uses: docker/[email protected] | |
| - name: Log in to the container registry | |
| uses: docker/[email protected] | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure image tags | |
| id: tag_config | |
| shell: bash | |
| run: | | |
| BASE_CONFIG="type=sha,format=long" | |
| if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then | |
| BASE_CONFIG+=$'\n'"type=schedule,pattern=nightly" | |
| BASE_CONFIG+=$'\n'"type=schedule,pattern=nightly-{{date 'ddd'}}" | |
| elif [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| TAG_NAME="${GITHUB_REF#refs/tags/}" | |
| if [[ "$TAG_NAME" == v* ]]; then | |
| BASE_CONFIG="type=semver,pattern={{version}}" | |
| if [[ "$TAG_NAME" == v*-alpha* ]]; then | |
| BASE_CONFIG+=$'\n'"type=raw,value=latest" | |
| else | |
| BASE_CONFIG+=$'\n'"type=raw,value=stable" | |
| BASE_CONFIG+=$'\n'"type=raw,value=latest" | |
| fi | |
| fi | |
| fi | |
| { | |
| echo 'TAGS_SPEC<<EOF' | |
| echo "$BASE_CONFIG" | |
| echo EOF | |
| } >> $GITHUB_ENV | |
| - name: Get current date (RFC 3339 format) | |
| id: date | |
| run: echo "date=$(date -Iseconds)" >> $GITHUB_OUTPUT | |
| - name: Extract metadata for Docker | |
| id: meta | |
| uses: docker/[email protected] | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| flavor: latest=false | |
| tags: ${{ env.TAGS_SPEC }} | |
| labels: | | |
| org.opencontainers.image.version=${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || '' }} | |
| org.opencontainers.image.created=${{ steps.date.outputs.date }} | |
| org.opencontainers.image.ref.name=${{ github.ref_name }} | |
| org.opencontainers.image.vendor=we-promise | |
| org.opencontainers.image.title=Sure | |
| org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app | |
| - name: Publish 'linux/${{ matrix.platform }}' image by digest | |
| uses: docker/[email protected] | |
| id: build | |
| with: | |
| context: . | |
| build-args: BUILD_COMMIT_SHA=${{ github.sha }} | |
| platforms: 'linux/${{ matrix.platform }}' | |
| cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache-${{ matrix.platform }} | |
| cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache-${{ matrix.platform }},mode=max | |
| labels: ${{ steps.meta.outputs.labels }} | |
| provenance: false | |
| push: true | |
| # DO NOT REMOVE `oci-mediatypes=true`, fixes annotation not showing up on job.merge.steps[-1] | |
| # ref: https://github.com/docker/build-push-action/discussions/1022 | |
| outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},name-canonical=true,push-by-digest=true,oci-mediatypes=true | |
| - name: Export the Docker image digest | |
| if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }} | |
| run: | | |
| mkdir -p "${RUNNER_TEMP}"/digests | |
| echo "${DIGEST#sha256:}" > "${RUNNER_TEMP}/digests/digest-${PLATFORM}" | |
| env: | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| PLATFORM: ${{ matrix.platform }} | |
| - name: Upload the Docker image digest | |
| if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }} | |
| uses: actions/[email protected] | |
| with: | |
| name: digest-${{ matrix.platform }} | |
| path: ${{ runner.temp }}/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| merge: | |
| name: Merge multi-arch manifest & push multi-arch tag | |
| if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }} | |
| needs: [build] | |
| timeout-minutes: 60 | |
| runs-on: 'ubuntu-24.04' | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Set up Docker Buildx | |
| uses: docker/[email protected] | |
| - name: Download Docker image digests | |
| uses: actions/[email protected] | |
| with: | |
| path: ${{ runner.temp }}/digests | |
| pattern: digest-* | |
| merge-multiple: true | |
| - name: Log in to the container registry | |
| uses: docker/[email protected] | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Merge and push Docker image | |
| env: | |
| TAGS: ${{ needs.build.outputs.tags }} | |
| DIGESTS_DIR: ${{ runner.temp }}/digests | |
| shell: bash -xeuo pipefail {0} | |
| run: | | |
| tag_args=() | |
| while IFS=$'\n' read -r tag; do | |
| [[ -n "${tag}" ]] || continue | |
| tag_args+=("--tag=${tag}") | |
| done <<< "${TAGS}" | |
| image_args=() | |
| for PLATFORM in amd64 arm64; do | |
| image_args+=("${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:$(<"${DIGESTS_DIR}/digest-${PLATFORM}")") | |
| done | |
| annotations=( | |
| "index:org.opencontainers.image.created=$(date -Iseconds)" | |
| 'index:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}' | |
| 'index:org.opencontainers.image.revision=${{ github.sha }}' | |
| 'index:org.opencontainers.image.ref.name=${{ github.ref_name }}' | |
| 'index:org.opencontainers.image.vendor=we-promise' | |
| 'index:org.opencontainers.image.licenses=AGPL-3.0' | |
| 'index:org.opencontainers.image.title=Sure' | |
| 'index:org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app' | |
| ) | |
| annotation_args=() | |
| for annotation in "${annotations[@]}"; do | |
| annotation_args+=("--annotation=${annotation}") | |
| done | |
| if [[ $GITHUB_REF_TYPE == "tag" ]]; then | |
| annotation_args+=("--annotation=index:org.opencontainers.image.version=$GITHUB_REF_NAME") | |
| fi | |
| attempts=0 | |
| until docker buildx imagetools create \ | |
| "${annotation_args[@]}" \ | |
| "${tag_args[@]}" \ | |
| "${image_args[@]}" \ | |
| ; do | |
| attempts=$((attempts + 1)) | |
| if [[ $attempts -ge 3 ]]; then | |
| echo "[$(date -u)] ERROR: Failed after 3 attempts." >&2 | |
| exit 1 | |
| fi | |
| delay=$((2 ** attempts)) | |
| if [[ $delay -gt 15 ]]; then delay=15; fi | |
| echo "Push failed (attempt $attempts). Retrying in ${delay} seconds..." | |
| sleep ${delay} | |
| done | |
| mobile: | |
| name: Build Mobile Apps | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: ./.github/workflows/flutter-build.yml | |
| secrets: inherit | |
| release: | |
| name: Create GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: [merge, mobile] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download Android APK artifact | |
| uses: actions/[email protected] | |
| with: | |
| name: app-release-apk | |
| path: ${{ runner.temp }}/mobile-artifacts | |
| - name: Download iOS build artifact | |
| uses: actions/[email protected] | |
| with: | |
| name: ios-build-unsigned | |
| path: ${{ runner.temp }}/ios-build | |
| - name: Prepare release assets | |
| run: | | |
| mkdir -p ${{ runner.temp }}/release-assets | |
| echo "=== Debugging: List downloaded artifacts ===" | |
| echo "Mobile artifacts:" | |
| ls -laR "${{ runner.temp }}/mobile-artifacts" || echo "No mobile-artifacts directory" | |
| echo "iOS build:" | |
| ls -laR "${{ runner.temp }}/ios-build" || echo "No ios-build directory" | |
| echo "===========================================" | |
| # Copy debug APK if it exists | |
| if [ -f "${{ runner.temp }}/mobile-artifacts/app-debug.apk" ]; then | |
| cp "${{ runner.temp }}/mobile-artifacts/app-debug.apk" "${{ runner.temp }}/release-assets/sure-${{ github.ref_name }}-debug.apk" | |
| echo "✓ Debug APK prepared" | |
| fi | |
| # Copy release APK if it exists | |
| if [ -f "${{ runner.temp }}/mobile-artifacts/app-release.apk" ]; then | |
| cp "${{ runner.temp }}/mobile-artifacts/app-release.apk" "${{ runner.temp }}/release-assets/sure-${{ github.ref_name }}.apk" | |
| echo "✓ Release APK prepared" | |
| fi | |
| # Create iOS app archive (zip the .app bundle) | |
| # Path preserves directory structure from artifact upload | |
| if [ -d "${{ runner.temp }}/ios-build/ios/iphoneos/Runner.app" ]; then | |
| cd "${{ runner.temp }}/ios-build/ios/iphoneos" | |
| zip -r "${{ runner.temp }}/release-assets/sure-${{ github.ref_name }}-ios-unsigned.zip" Runner.app | |
| echo "✓ iOS build archive prepared" | |
| fi | |
| # Copy iOS build info | |
| if [ -f "${{ runner.temp }}/ios-build/ios-build-info.txt" ]; then | |
| cp "${{ runner.temp }}/ios-build/ios-build-info.txt" "${{ runner.temp }}/release-assets/" | |
| fi | |
| echo "Release assets:" | |
| ls -la "${{ runner.temp }}/release-assets/" | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: ${{ github.ref_name }} | |
| draft: false | |
| prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }} | |
| generate_release_notes: true | |
| files: | | |
| ${{ runner.temp }}/release-assets/* | |
| body: | | |
| ## Mobile Debug Builds | |
| This release includes debug builds of the mobile applications: | |
| - **Android APK**: Debug build for testing on Android devices | |
| - **iOS Build**: Unsigned iOS build (requires code signing for installation) | |
| > **Note**: These are debug builds intended for testing purposes. For production use, please build from source with proper signing credentials. | |
| bump-alpha-version: | |
| name: Bump Alpha Version | |
| if: startsWith(github.ref, 'refs/tags/v') && contains(github.ref_name, 'alpha') | |
| needs: [merge] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check out main branch | |
| uses: actions/[email protected] | |
| with: | |
| ref: main | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Bump alpha version | |
| run: | | |
| VERSION_FILE="config/initializers/version.rb" | |
| # Ensure version file exists | |
| if [ ! -f "$VERSION_FILE" ]; then | |
| echo "ERROR: Version file not found: $VERSION_FILE" | |
| exit 1 | |
| fi | |
| # Extract current version | |
| CURRENT_VERSION=$(grep -oP '"\K[0-9]+\.[0-9]+\.[0-9]+-alpha\.[0-9]+' "$VERSION_FILE") | |
| if [ -z "$CURRENT_VERSION" ]; then | |
| echo "ERROR: Could not extract version from $VERSION_FILE" | |
| exit 1 | |
| fi | |
| echo "Current version: $CURRENT_VERSION" | |
| # Extract the alpha number and increment it | |
| ALPHA_NUM=$(echo "$CURRENT_VERSION" | grep -oP 'alpha\.\K[0-9]+') | |
| if [ -z "$ALPHA_NUM" ]; then | |
| echo "ERROR: Could not extract alpha number from $CURRENT_VERSION" | |
| exit 1 | |
| fi | |
| NEW_ALPHA_NUM=$((ALPHA_NUM + 1)) | |
| # Create new version string | |
| BASE_VERSION=$(echo "$CURRENT_VERSION" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+') | |
| if [ -z "$BASE_VERSION" ]; then | |
| echo "ERROR: Could not extract base version from $CURRENT_VERSION" | |
| exit 1 | |
| fi | |
| NEW_VERSION="${BASE_VERSION}-alpha.${NEW_ALPHA_NUM}" | |
| echo "New version: $NEW_VERSION" | |
| # Update the version file | |
| sed -i "s/\"$CURRENT_VERSION\"/\"$NEW_VERSION\"/" "$VERSION_FILE" | |
| # Verify the change | |
| echo "Updated version.rb:" | |
| - name: Commit and push version bump | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add config/initializers/version.rb | |
| # Check if there are changes to commit | |
| if git diff --cached --quiet; then | |
| echo "No changes to commit - version may have already been bumped" | |
| exit 0 | |
| git commit -m "Bump version to next alpha after ${{ github.ref_name }} release" | |
| # Push with retry logic | |
| attempts=0 | |
| until git push origin main; do | |
| attempts=$((attempts + 1)) | |
| if [[ $attempts -ge 4 ]]; then | |
| echo "ERROR: Failed to push after 4 attempts." >&2 | |
| exit 1 | |
| fi | |
| delay=$((2 ** attempts)) | |
| echo "Push failed (attempt $attempts). Retrying in ${delay} seconds..." | |
| sleep ${delay} | |
| git pull --rebase origin main | |
| done |