diff --git a/.github/workflows/build-swift.yml b/.github/workflows/build-swift.yml new file mode 100644 index 000000000..92be9a456 --- /dev/null +++ b/.github/workflows/build-swift.yml @@ -0,0 +1,102 @@ +--- +name: Build Swift Package + +on: + push: + branches: + - "rc" + - "hotfix-rc" + - "main" + +jobs: + version: + name: Get Version + runs-on: ubuntu-22.04 + outputs: + package_version: ${{ steps.retrieve-version.outputs.package_version }} + steps: + - name: Checkout repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Get Package Version + id: retrieve-version + run: | + VERSION=$(grep -o '^version = ".*"' Cargo.toml | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+") + echo "package_version=$VERSION" >> $GITHUB_OUTPUT + + build: + name: Build + runs-on: macos-13 + needs: version + env: + _VERSION: ${{ needs.version.outputs.package_version }} + steps: + - name: Checkout repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Install rust + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable + with: + toolchain: stable + + - name: Cache cargo registry + uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + with: + key: sdk-swift-cargo + + - name: Rustup target + run: | + rustup target install aarch64-apple-ios-sim + rustup target install aarch64-apple-ios + rustup target install x86_64-apple-ios + + - name: Build + shell: bash + working-directory: languages/swift + id: build + run: | + ./build.sh + + # SHA Short + echo "short-sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Upload BitwardenFFI.xcframework artifact + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + with: + name: BitwardenFFI-${{ env._VERSION }}-${{ steps.build.outputs.short-sha }}.xcframework + path: languages/swift/BitwardenFFI.xcframework + if-no-files-found: error + + trigger-swift-release: + name: Trigger Swift release + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-22.04 + needs: build + steps: + - name: Login to Azure - CI Subscription + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve github PAT secrets + id: retrieve-secret-pat + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: "bitwarden-ci" + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Trigger Swift release + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: 'bitwarden', + repo: 'sdk', + workflow_id: 'release-swift.yml', + ref: 'main', + inputs: { + 'build-run-id': '${{ github.run_id }}', + 'pre-release': 'true' + } + }) diff --git a/.github/workflows/release-swift.yml b/.github/workflows/release-swift.yml new file mode 100644 index 000000000..954480365 --- /dev/null +++ b/.github/workflows/release-swift.yml @@ -0,0 +1,223 @@ +--- +name: Release Swift Package + +on: + workflow_call: + inputs: + build-run-id: + description: "Workflow Run ID to use for artifact download. If not provided the latest build from the selected branch will be used." + type: string + required: false + pre-release: + description: "Create a pre-release" + type: boolean + required: false + default: false + + workflow_dispatch: + inputs: + pre-release: + description: "Create a pre-release" + type: boolean + required: false + default: false + +env: + _KEY_VAULT: "bitwarden-ci" + +jobs: + validate: + name: Set Version and SHA + runs-on: ubuntu-22.04 + outputs: + version: ${{ steps.version.outputs.version }} + sha: ${{ steps.set-sha.outputs.sha }} + short_sha: ${{ steps.set-sha.outputs.short_sha }} + release_name: ${{ steps.set-release-name.outputs.release_name }} + run_id: ${{ steps.get-run-id.outputs.build-run-id }} + swift_checksum: ${{ steps.calculate-swift-checksum.outputs.checksum }} + steps: + - name: Checkout repo + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + - name: Get version + id: version + run: | + VERSION=$(grep -o '^version = ".*"' crates/bitwarden/Cargo.toml | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+") + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Get run id + id: get-run-id + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + run: | + if [[ -z ${{ inputs.build-run-id }} ]]; then + BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} + RUN_ID=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/$OWNER/$REPO/actions/workflows/build-swift.yml/runs \ + | jq -r ".workflow_runs[] | select(.head_branch == \"$BRANCH\") | .id") + else + RUN_ID=${{ inputs.build-run-id }} + fi + + echo "build-run-id=$RUN_ID" >> $GITHUB_OUTPUT + + - name: Download BitwardenEFI artifact + uses: bitwarden/gh-actions/download-artifacts@main + id: download-artifact + with: + workflow: build-swift.yml + workflow_conclusion: success + skip_unpack: true + run_id: ${{ steps.get-run-id.outputs.build-run-id }} + + - name: Set SHA + id: set-sha + run: | + echo "sha=$(${{ steps.download-artifact.outputs.artifact-build-commit }})" >> $GITHUB_OUTPUT + echo "short_sha=$(echo ${{ steps.download-artifact.outputs.artifact-build-commit }} | cut -c1-7)" >> $GITHUB_OUTPUT + + - name: Set release name + id: set-release-name + run: | + if [[ ${{ inputs.pre-release }} == true ]]; then + echo "release_name=${{ steps.version.outputs.version }}-unstable-${{ steps.set-sha.outputs.short_sha }}" >> $GITHUB_OUTPUT + else + echo "release_name=${{ steps.version.outputs.version }}" >> $GITHUB_OUTPUT + fi + + - name: Calculate swift file checksum + id: calculate-swift-checksum + run: | + CHECKSUM=$(swift package compute-checksum BitwardenFFI-${{ steps.version.outputs.version }}-${{ steps.set-sha.outputs.short_sha }}.xcframework.zip) + echo "checksum=$CHECKSUM" >> $GITHUB_OUTPUT + + repo-sync: + name: Push changed files to SDK Swift repo + runs-on: ubuntu-22.04 + needs: validate + env: + _BOT_EMAIL: 106330231+bitwarden-devops-bot@users.noreply.github.com + _BOT_NAME: bitwarden-devops-bot + _PKG_VERSION: ${{ needs.validate.outputs.version }} + _PRE_RELEASE: ${{ inputs.pre-release }} + _RELEASE_NAME: ${{ needs.validate.outputs.release_name }} + _SWIFT_CHECKSUM: ${{ needs.validate.outputs.swift_checksum }} + steps: + - name: Checkout SDK repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + with: + path: sdk + + - name: Get ref from SDK repo + id: get-ref + run: | + if [[ $_PRE_RELEASE == true ]]; then + echo "ref=unstable" >> $GITHUB_OUTPUT + else + echo "ref=main" >> $GITHUB_OUTPUT + fi + + - name: Checkout SDK-Swift repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + with: + repository: bitwarden/sdk-swift + path: sdk-swift + ref: ${{ steps.get-ref.outputs.ref }} + + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Setup Git + working-directory: sdk-swift + run: | + git config --local user.email "${{ env._BOT_EMAIL }}" + git config --local user.name "${{ env._BOT_NAME }}" + + - name: Update files + run: | + # Update BitwardenFFI path + sed -i '' 's|.binaryTarget(name: "BitwardenFFI", path: "BitwardenFFI.xcframework")|.binaryTarget(\ + name: "BitwardenFFI",\ + url: "https://github.com/bitwarden/sdk-swift/releases/download/v${{ env._RELEASE_NAME }}/BitwardenFFI-${{ env._PKG_VERSION }}-${{ needs.validate.outputs.short_sha }}.xcframework.zip",\ + checksum: "${{ env._SWIFT_CHECKSUM }}"|' sdk/languages/swift/Package.swift + + # Run swiftformat + swiftformat sdk/languages/swift/Package.swift + + # Copy files to local sdk-swift repo path + cp --verbose -rf sdk/languages/swift/README.md sdk-swift/README.md + cp --verbose -rf sdk/languages/swift/Package.swift sdk-swift/Package.swift + cp --verbose -rf sdk/languages/swift/Sources sdk-swift/Sources + cp --verbose -rf sdk/languages/swift/Tests sdk-swift/Tests + + - name: Push changes + working-directory: sdk-swift + run: | + git add . + git commit -m "Update Swift SDK to ${{ needs.validate.outputs.sha }}" + git push origin ${{ steps.get-ref.outputs.ref }} + + - name: Create release tag on SDK Swift repo + working-directory: sdk-swift + run: | + git tag v${{ env._RELEASE_NAME }} + git push origin v${{ env._RELEASE_NAME }} + + github-release: + name: GitHub Release + runs-on: ubuntu-22.04 + needs: + - validate + - repo-sync + env: + _PKG_VERSION: ${{ needs.validate.outputs.version }} + _RELEASE_NAME: ${{ needs.validate.outputs.release_name }} + _BUILD_RUN_ID: ${{ needs.validate.outputs.run_id }} + steps: + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Download BitwardenEFI artifact + uses: bitwarden/gh-actions/download-artifacts@main + id: download-artifact + with: + workflow: build-swift.yml + workflow_conclusion: success + artifacts: "BitwardenFFI-${{ env._PKG_VERSION }}-${{ needs.validate.outputs.short_sha }}.xcframework" + run_id: ${{ env._BUILD_RUN_ID }} + + - name: Create release + uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 + with: + tag: v${{ env._RELEASE_NAME }} + name: v${{ env._RELEASE_NAME }} + body: "" + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + draft: false + repo: sdk-swift + owner: bitwarden + artifacts: "BitwardenFFI-${{ env._PKG_VERSION }}-${{ needs.validate.outputs.short_sha }}.xcframework" + prerelease: ${{ inputs.pre-release }}