--- name: github-release on: push: tags: - v[0-9]+.[0-9]+.[0-9]+* workflow_dispatch: inputs: tag: description: "Release tag (e.g., v2.10.0)" required: true type: string env: RELEASE_TAG: ${{ inputs.tag || github.ref_name }} SNYK_VERSION: "1.1297.2" CYCLONEDX_VERSION: "v0.27.2" INTUNE_ENABLED: 'true' jobs: test: runs-on: ubuntu-22.04 steps: - name: ci/checkout-repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: ci/test uses: ./.github/actions/test build-ios-unsigned: runs-on: macos-15-large needs: - test steps: - name: ci/checkout-repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: ci/setup-ssh-key uses: ./.github/actions/setup-ssh-key with: ssh-private-key: ${{ secrets.MM_MOBILE_PRIVATE_DEPLOY_KEY }} - name: ci/prepare-ios-build uses: ./.github/actions/prepare-ios-build with: intune-enabled: ${{ env.INTUNE_ENABLED }} intune-ssh-private-key: ${{ secrets.MM_MOBILE_INTUNE_DEPLOY_KEY }} - name: ci/build-ios-unsigned env: TAG: "${{ env.RELEASE_TAG }}" GITHUB_TOKEN: "${{ secrets.MM_MOBILE_GITHUB_TOKEN }}" run: bundle exec fastlane ios unsigned working-directory: ./fastlane - name: ci/upload-ios-unsigned uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: path: Mattermost-unsigned.ipa name: Mattermost-unsigned.ipa - name: ci/install-snyk run: npm install -g snyk@${{ env.SNYK_VERSION }} - name: ci/generate-ios-sbom env: SNYK_TOKEN: "${{ secrets.SNYK_TOKEN }}" run: | snyk sbom --format=cyclonedx1.6+json --json-file-output=../sbom-ios.json --all-projects working-directory: ./ios shell: bash - name: ci/upload-ios-sbom uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: path: sbom-ios.json name: sbom-ios.json build-android-unsigned: runs-on: ubuntu-22.04 needs: - test steps: - name: ci/checkout-repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: ci/prepare-android-build uses: ./.github/actions/prepare-android-build with: sign: false - name: ci/build-android-beta env: TAG: "${{ env.RELEASE_TAG }}" GITHUB_TOKEN: "${{ secrets.MM_MOBILE_GITHUB_TOKEN }}" run: bundle exec fastlane android unsigned working-directory: ./fastlane - name: ci/upload-android-unsigned-build uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: path: Mattermost-unsigned.apk name: Mattermost-unsigned.apk - name: ci/install-snyk run: npm install -g snyk@${{ env.SNYK_VERSION }} - name: ci/generate-android-sbom env: SNYK_TOKEN: "${{ secrets.SNYK_TOKEN }}" run: | snyk sbom --format=cyclonedx1.6+json --all-projects --json-file-output=../sbom-android.json working-directory: ./android shell: bash - name: ci/upload-android-sbom uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: path: sbom-android.json name: sbom-android.json generate-consolidated-sbom: runs-on: ubuntu-22.04 needs: - build-ios-unsigned - build-android-unsigned steps: - name: ci/checkout-repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: ci/download-sboms uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: sbom-*.json path: ${{ github.workspace }} merge-multiple: true - name: ci/install-snyk run: npm install -g snyk@${{ env.SNYK_VERSION }} - name: ci/setup-cyclonedx-cli run: | set -e CYCLONEDX_BINARY="cyclonedx-linux-x64" CYCLONEDX_URL="https://github.com/CycloneDX/cyclonedx-cli/releases/download/${{ env.CYCLONEDX_VERSION }}/${CYCLONEDX_BINARY}" # Download with better error handling and retry echo "Downloading CycloneDX CLI ${{ env.CYCLONEDX_VERSION }}..." curl -sSfL --retry 3 --retry-delay 5 "${CYCLONEDX_URL}" -o cyclonedx # Verify the binary is executable and not corrupted if [ ! -s cyclonedx ]; then echo "Error: Downloaded file is empty or corrupted" exit 1 fi # Make executable and move to PATH chmod +x cyclonedx sudo mv cyclonedx /usr/local/bin/ # Verify installation cyclonedx --version - name: ci/generate-consolidated-sbom env: SNYK_TOKEN: "${{ secrets.SNYK_TOKEN }}" SBOM_FILENAME: "sbom-${{ github.event.repository.name }}-${{ env.RELEASE_TAG }}.json" run: | # Check if required SBOM files are available if [ ! -f "sbom-android.json" ]; then echo "Error: sbom-android.json not found. Android SBOM generation may have failed." exit 1 fi if [ ! -f "sbom-ios.json" ]; then echo "Error: sbom-ios.json not found. iOS SBOM generation may have failed." exit 1 fi echo "All required SBOM files are available. Proceeding with consolidation..." # Generate top-level SBOM snyk sbom --format=cyclonedx1.6+json --json-file-output=sbom-top-level.json # Consolidate SBOMs cyclonedx merge \ --input-files "sbom-top-level.json" "sbom-android.json" "sbom-ios.json" \ --input-format=json \ --output-file="$SBOM_FILENAME" \ --output-format=json \ --output-version=v1_6 # Validate the consolidated SBOM cyclonedx validate --input-file="$SBOM_FILENAME" shell: bash - name: ci/upload-consolidated-sbom uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: path: sbom-${{ github.event.repository.name }}-${{ env.RELEASE_TAG }}.json name: sbom-${{ github.event.repository.name }}-${{ env.RELEASE_TAG }}.json release: runs-on: ubuntu-22.04 needs: - build-ios-unsigned - build-android-unsigned - generate-consolidated-sbom steps: - name: ci/checkout-repo uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ruby/setup-ruby@cb0fda56a307b8c78d38320cd40d9eb22a3bf04e # v1.242.0 - name: release/setup-fastlane-dependencies run: bundle install working-directory: ./fastlane - name: ci/download-artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: path: ${{ github.workspace }} merge-multiple: true - name: release/create-github-release env: GITHUB_TOKEN: "${{ secrets.MM_MOBILE_GITHUB_TOKEN }}" run: bundle exec fastlane github working-directory: ./fastlane - name: release/upload-sbom-to-release env: GITHUB_TOKEN: "${{ secrets.MM_MOBILE_GITHUB_TOKEN }}" run: | gh release upload "${{ env.RELEASE_TAG }}" "sbom-${{ github.event.repository.name }}-${{ env.RELEASE_TAG }}.json"