diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52fabbab0..6dfb74f34 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,6 +58,10 @@ jobs: - name: Install Ionic CLI run: npm install -g @ionic/cli + - name: Normalize Dependabot package lock + if: github.event.pull_request.user.login == 'dependabot[bot]' + run: npm install --package-lock-only --ignore-scripts + - name: Install dependencies run: npm ci diff --git a/.github/workflows/dependabot-lockfile-normalize.yml b/.github/workflows/dependabot-lockfile-normalize.yml index 084ac43cc..a05fb4583 100644 --- a/.github/workflows/dependabot-lockfile-normalize.yml +++ b/.github/workflows/dependabot-lockfile-normalize.yml @@ -9,6 +9,7 @@ on: - package-lock.json permissions: + actions: write contents: write pull-requests: read @@ -33,7 +34,7 @@ jobs: uses: actions/checkout@v7 with: repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false - name: Use Node.js @@ -43,6 +44,7 @@ jobs: - name: Verify Dependabot branch guard env: + EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha }} HEAD_REF: ${{ github.event.pull_request.head.ref }} HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} @@ -65,19 +67,43 @@ jobs: ;; esac + if [ "$(git rev-parse HEAD)" != "$EXPECTED_HEAD_SHA" ]; then + echo "Checked out an unexpected commit." + exit 1 + fi + - name: Normalize package lock run: npm install --package-lock-only --ignore-scripts - name: Commit normalized package lock env: - GITHUB_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ github.token }} HEAD_REF: ${{ github.event.pull_request.head.ref }} + PR_NUMBER: ${{ github.event.pull_request.number }} run: | if git diff --quiet -- package-lock.json; then echo "package-lock.json is already normalized." exit 0 fi + unexpected_pr_files="" + while IFS= read -r file; do + case "$file" in + package.json|package-lock.json) ;; + *) unexpected_pr_files="${unexpected_pr_files}${unexpected_pr_files:+$'\n'}${file}" ;; + esac + done < <( + gh api --paginate \ + "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" \ + --jq '.[].filename' + ) + + if [ -n "$unexpected_pr_files" ]; then + echo "Refusing to approve a Dependabot PR with unexpected files:" + printf '%s\n' "$unexpected_pr_files" + exit 1 + fi + changed_files="$(git diff --name-only)" if [ "$changed_files" != "package-lock.json" ]; then echo "Unexpected files changed:" @@ -89,5 +115,46 @@ jobs: git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add package-lock.json git commit -m "chore(deps): normalize package lock" - auth_header="$(printf 'x-access-token:%s' "$GITHUB_TOKEN" | base64 | tr -d '\n')" + normalized_sha="$(git rev-parse HEAD)" + auth_header="$(printf 'x-access-token:%s' "$GH_TOKEN" | base64 | tr -d '\n')" git -c http.extraheader="AUTHORIZATION: basic ${auth_header}" push origin "HEAD:${HEAD_REF}" + + # GITHUB_TOKEN pushes do not trigger push workflows, so dispatch tests + # explicitly against the normalized Dependabot branch. + gh workflow run test.yml --ref "$HEAD_REF" + + # GitHub creates pull_request workflows from GITHUB_TOKEN updates in + # an approval-required state. Approve only build.yml for this exact SHA. + build_run_found=false + for attempt in $(seq 1 15); do + build_run="$( + gh api --method GET \ + "repos/${GITHUB_REPOSITORY}/actions/runs" \ + -f event=pull_request \ + -f head_sha="$normalized_sha" \ + -f per_page=100 \ + --jq '.workflow_runs[] | select(.path == ".github/workflows/build.yml") | [.id, .status, (.conclusion // "")] | @tsv' \ + | head -n 1 + )" + + if [ -n "$build_run" ]; then + build_run_found=true + IFS=$'\t' read -r build_run_id build_run_status build_run_conclusion <<< "$build_run" + + if [ "$build_run_conclusion" = "action_required" ]; then + gh api --method POST \ + "repos/${GITHUB_REPOSITORY}/actions/runs/${build_run_id}/approve" + echo "Approved build workflow run ${build_run_id}." + else + echo "Build workflow run ${build_run_id} is ${build_run_status}/${build_run_conclusion:-pending}." + fi + break + fi + + sleep 2 + done + + if [ "$build_run_found" != "true" ]; then + echo "No build workflow run appeared for normalized commit ${normalized_sha}." + exit 1 + fi diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03bc834f7..062094bfd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,8 @@ name: test -on: push +on: + push: + workflow_dispatch: permissions: contents: read @@ -21,6 +23,10 @@ jobs: - name: Install Ionic CLI run: npm install -g @ionic/cli + - name: Normalize Dependabot package lock + if: startsWith(github.ref_name, 'dependabot/npm_and_yarn/') + run: npm install --package-lock-only --ignore-scripts + - name: Install dependencies run: npm ci @@ -42,6 +48,10 @@ jobs: - name: Install Ionic CLI run: npm install -g @ionic/cli + - name: Normalize Dependabot package lock + if: startsWith(github.ref_name, 'dependabot/npm_and_yarn/') + run: npm install --package-lock-only --ignore-scripts + - name: Install dependencies run: npm ci diff --git a/ios/App/CapApp-SPM/Package.swift b/ios/App/CapApp-SPM/Package.swift index aadbb9087..42ae14b0c 100644 --- a/ios/App/CapApp-SPM/Package.swift +++ b/ios/App/CapApp-SPM/Package.swift @@ -11,7 +11,7 @@ let package = Package( targets: ["CapApp-SPM"]) ], dependencies: [ - .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.4.1"), + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.4.2"), .package(name: "CapacitorCommunityAdvertisingId", path: "../../../node_modules/@capacitor-community/advertising-id"), .package(name: "CapacitorCommunityBluetoothLe", path: "../../../node_modules/@capacitor-community/bluetooth-le"), .package(name: "CapacitorApp", path: "../../../node_modules/@capacitor/app"), diff --git a/ios/capacitor-cordova-ios-plugins/sources/CordovaPluginPurchase/Package.swift b/ios/capacitor-cordova-ios-plugins/sources/CordovaPluginPurchase/Package.swift index 4c01f5fe5..d4542370e 100644 --- a/ios/capacitor-cordova-ios-plugins/sources/CordovaPluginPurchase/Package.swift +++ b/ios/capacitor-cordova-ios-plugins/sources/CordovaPluginPurchase/Package.swift @@ -12,7 +12,7 @@ let package = Package( ) ], dependencies: [ - .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.4.1") + .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.4.2") ], targets: [ .target( diff --git a/package-lock.json b/package-lock.json index 90840538d..e18d711ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,26 +20,26 @@ "@angular/router": "^21.2.18", "@capacitor-community/advertising-id": "^8.0.0", "@capacitor-community/bluetooth-le": "^8.2.0", - "@capacitor/android": "^8.4.1", - "@capacitor/app": "^8.1.0", - "@capacitor/browser": "^8.0.3", + "@capacitor/android": "^8.4.2", + "@capacitor/app": "^8.1.1", + "@capacitor/browser": "^8.0.4", "@capacitor/camera": "^8.2.1", "@capacitor/clipboard": "^8.0.1", - "@capacitor/core": "^8.4.1", - "@capacitor/device": "^8.0.2", + "@capacitor/core": "^8.4.2", + "@capacitor/device": "^8.0.3", "@capacitor/filesystem": "^8.1.2", "@capacitor/geolocation": "^8.2.0", - "@capacitor/ios": "^8.4.1", - "@capacitor/local-notifications": "^8.2.0", + "@capacitor/ios": "^8.4.2", + "@capacitor/local-notifications": "^8.2.1", "@capacitor/network": "^8.0.1", "@capacitor/preferences": "^8.0.1", - "@capacitor/push-notifications": "^8.1.1", + "@capacitor/push-notifications": "^8.1.2", "@capacitor/share": "^8.0.1", - "@capacitor/splash-screen": "^8.0.1", + "@capacitor/splash-screen": "^8.0.2", "@capawesome/capacitor-android-edge-to-edge-support": "^8.0.8", - "@capgo/capacitor-social-login": "^8.3.35", - "@capgo/capacitor-wifi": "^8.4.0", - "@ionic/angular": "^8.8.13", + "@capgo/capacitor-social-login": "^8.3.37", + "@capgo/capacitor-wifi": "^8.4.1", + "@ionic/angular": "^8.8.14", "@ionic/core": "^8.7.17", "@ionic/pwa-elements": "^3.0.2", "@jsverse/transloco": "^8.4.0", @@ -3905,27 +3905,27 @@ } }, "node_modules/@capacitor/android": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.4.1.tgz", - "integrity": "sha512-igtDCJ7QQn0P2qHFD9p4KXaa6V1b2PRNt+MxjVwtjTm/BJvqmiazOJq6rPjwFSZnfHm6iFoZk8TfzHd44pyBGw==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.4.2.tgz", + "integrity": "sha512-bzf8XZ9C+ePgOQ+e+T0fnhHGH4aCNY494vvSQIF5w4AY07RwEmkFqZs1678DDSMH0hLSQpxEwXGFNUVcXO6bBA==", "license": "MIT", "peerDependencies": { "@capacitor/core": "^8.4.0" } }, "node_modules/@capacitor/app": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@capacitor/app/-/app-8.1.0.tgz", - "integrity": "sha512-MlmttTOWHDedr/G4SrhNRxsXMqY+R75S4MM4eIgzsgCzOYhb/MpCkA5Q3nuOCfL1oHm26xjUzqZ5aupbOwdfYg==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@capacitor/app/-/app-8.1.1.tgz", + "integrity": "sha512-xM2ZTX5jK60tFtmjsmJv+Cdj1Qsb6NcavkqmdEnCPQBeya9oKhamZJxYOnQNj1ZvcJM7sWfG6BEtSLx42pisbA==", "license": "MIT", "peerDependencies": { "@capacitor/core": ">=8.0.0" } }, "node_modules/@capacitor/browser": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/@capacitor/browser/-/browser-8.0.3.tgz", - "integrity": "sha512-WJWPHEPbweiFoHYmVlCbZf5yrqJ2Rchx2Xvbmd+3Lf+Zkpq3nXBThThY2CF69lYEg1NINGF9BcHThIOEU1gZlQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@capacitor/browser/-/browser-8.0.4.tgz", + "integrity": "sha512-ORZ4u/y+7aMuu6yVuk6SP529fUZyqcbnuHB1q5McpA3o2SYfVoi28iB8rsQjI2ad1qlKJd29ZUuGtspXLBDlWg==", "license": "MIT", "peerDependencies": { "@capacitor/core": ">=8.0.0" @@ -4040,18 +4040,18 @@ } }, "node_modules/@capacitor/core": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.4.1.tgz", - "integrity": "sha512-xqhOGLbTAYeOWK+IDUNSjQJAPapQjRHrIcgk9PYp52or9zFTaaMko31uNi16N6W+CRJ8VrRram6fOYILkBG2Hg==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.4.2.tgz", + "integrity": "sha512-fQPRb3JXRaU2pnufDUvqOjhsrYxDQeFRZyaj/sHydIUxD2NxOGHKMpmKUdI+U4OOmKuGZyvRpi7TSJU+7Bjbmg==", "license": "MIT", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@capacitor/device": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@capacitor/device/-/device-8.0.2.tgz", - "integrity": "sha512-fIqSXnG0s6bz5A/0xFgSXDkbU+Xl65ti80LhucNvLI4kGhJzcNn6SwWVwpXN9SJTOFWXblXknHNppheP8X1frQ==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@capacitor/device/-/device-8.0.3.tgz", + "integrity": "sha512-rliPCCZwxtjU6200jJNDAsQhioyozV3fGgiP+NgRqtDOI7i+Jdz+DYNwEup+3MGZZ4NEmkuFaBeWLM3T01vJRg==", "license": "MIT", "peerDependencies": { "@capacitor/core": ">=8.0.0" @@ -4082,18 +4082,18 @@ } }, "node_modules/@capacitor/ios": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.4.1.tgz", - "integrity": "sha512-EgcAk7NYheHMTyP3CUrA65qKs4D2UEAKgw44HI6Uk3dTw6KjLQkdLOQWvbeRncHaZ2gklfOojUoc5DlSw2lhYg==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-8.4.2.tgz", + "integrity": "sha512-ClVzIjK++yRjsRPOpdEzhsZfbHfoEc0f4M6vD0v7sWh0qcoF6NkxNAeHpWTn4OPJpJfpGGoYsq+IfEHrYyBiWA==", "license": "MIT", "peerDependencies": { "@capacitor/core": "^8.4.0" } }, "node_modules/@capacitor/local-notifications": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@capacitor/local-notifications/-/local-notifications-8.2.0.tgz", - "integrity": "sha512-fvLY0w2w4MiX+DD4+Wv4DOwOLdzKZsMDwAcRv/Juudd+QbKbn69s6cM3xVqPwAiDqfnqsY4/S8xtQD6M73wY2A==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@capacitor/local-notifications/-/local-notifications-8.2.1.tgz", + "integrity": "sha512-Bkim+MGl7UrDTjDferV4ECq0aWciTsa0k15+MX2jnx2PeWgEPvlBy5yrqzBlwEZPrtHFUvPVxPi5V66MPGHkAw==", "license": "MIT", "peerDependencies": { "@capacitor/core": ">=8.0.0" @@ -4118,9 +4118,9 @@ } }, "node_modules/@capacitor/push-notifications": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@capacitor/push-notifications/-/push-notifications-8.1.1.tgz", - "integrity": "sha512-WqzjPKIbYbARMN+GC0XMAJcxJpUUzqgzS/Ny8RODLrro38pQhm3GXYwX2Mwd+LZlLY39rGImkCkrKyQSNfuikA==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@capacitor/push-notifications/-/push-notifications-8.1.2.tgz", + "integrity": "sha512-TQl4XxqJfNF+KbSYBFMXYYT5WXUaleVKXlByhh/8+KySMVNjp+l5OqAUoGe/sY1IAnGXEuUeCjA/WLZEVvGwrA==", "license": "MIT", "peerDependencies": { "@capacitor/core": ">=8.0.0" @@ -4136,9 +4136,9 @@ } }, "node_modules/@capacitor/splash-screen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-8.0.1.tgz", - "integrity": "sha512-c/ew/Z3eA7z8l06WoRAtzVF16VwYYrExmHmfGq1Cg675pVzaC/yuucB8/1xG1vhEfnW4fZ1KhSf/kzR1RiVYgg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-8.0.2.tgz", + "integrity": "sha512-0C6rYScr13WfAE9nPl4ScOQynmjFv9NT3Th+RZkD4ezYHmER6mcl1/lDYsv7jg3Rj3FOvLrlTlmNkUrr83kZzQ==", "license": "MIT", "peerDependencies": { "@capacitor/core": ">=8.0.0" @@ -4170,9 +4170,9 @@ } }, "node_modules/@capgo/capacitor-social-login": { - "version": "8.3.35", - "resolved": "https://registry.npmjs.org/@capgo/capacitor-social-login/-/capacitor-social-login-8.3.35.tgz", - "integrity": "sha512-SzK5eTSXI2J7z8+mF82i07NyiZJIHjyMxWNZuGW03WhwZ5svidB8KptJsxR5NUd+snQ3aJUWsyaVG3C+4FOxiA==", + "version": "8.3.37", + "resolved": "https://registry.npmjs.org/@capgo/capacitor-social-login/-/capacitor-social-login-8.3.37.tgz", + "integrity": "sha512-IGLIy8bBPf8ocWJB5XZAzGlsecKetaZyMuyXla7EZ8eSsNLjWeNsWDdEXUdZxTL3rFjRfBuyOTII9in7/EzivQ==", "license": "MPL-2.0", "dependencies": { "tslib": "^2.8.1" @@ -4182,9 +4182,9 @@ } }, "node_modules/@capgo/capacitor-wifi": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@capgo/capacitor-wifi/-/capacitor-wifi-8.4.0.tgz", - "integrity": "sha512-gqYMzrgZ4U1r8iOKKSU8iNePwRe6TkcWg8/umSysVMHyNcPrQLH2wCdeQz0p45ndFKCBzkO0dYJ8kEUUjpdYNg==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@capgo/capacitor-wifi/-/capacitor-wifi-8.4.1.tgz", + "integrity": "sha512-MhAp+PC9qbO2i4wKArXM4Vttxh7r4cq5yopJK1qasSjStosZPsdbFlpjFy+VbbwShTl+jx96vFV8Vm5k/hIpWw==", "license": "MPL-2.0", "peerDependencies": { "@capacitor/core": ">=8.0.0" @@ -5533,12 +5533,12 @@ } }, "node_modules/@ionic/angular": { - "version": "8.8.13", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.8.13.tgz", - "integrity": "sha512-YxTmE3tjBB425G/L0SUORN0h3+uxcnnMa8dTgDXevUlb+q+duCV63ybLP8e70rogj2NTp7TG8MUAHoCLIqIc0g==", + "version": "8.8.14", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.8.14.tgz", + "integrity": "sha512-LZpLnIaajvgdXlvbvCxxE3HxDjVkschMMoG+Je1puYGc9EPSzyqWLGP2Rwq7EOCjTXWt9qmoQhBoaP0u+N64jg==", "license": "MIT", "dependencies": { - "@ionic/core": "8.8.13", + "@ionic/core": "8.8.14", "ionicons": "^8.0.13", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -5579,9 +5579,9 @@ } }, "node_modules/@ionic/core": { - "version": "8.8.13", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.8.13.tgz", - "integrity": "sha512-f09pRxmOLxPvLeCK9kTTBiByaPeCrApwABAwkqeax08e1b4kDSyXD1nMGDT6ChTvUGxyt4/cPxLsEP68ku4+HQ==", + "version": "8.8.14", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.8.14.tgz", + "integrity": "sha512-xI1y1OqPFsEjVE6nvLdUpb77Xt4uy5cQrNbDT/sRM6RN3vMs2zOFWubeRaQkBf0WslFetiJ/5uAALS/mW4d4TA==", "license": "MIT", "dependencies": { "@stencil/core": "4.43.5", diff --git a/package.json b/package.json index 23c5fdcf6..7b5118dea 100644 --- a/package.json +++ b/package.json @@ -37,26 +37,26 @@ "@angular/router": "^21.2.18", "@capacitor-community/advertising-id": "^8.0.0", "@capacitor-community/bluetooth-le": "^8.2.0", - "@capacitor/android": "^8.4.1", - "@capacitor/app": "^8.1.0", - "@capacitor/browser": "^8.0.3", + "@capacitor/android": "^8.4.2", + "@capacitor/app": "^8.1.1", + "@capacitor/browser": "^8.0.4", "@capacitor/camera": "^8.2.1", "@capacitor/clipboard": "^8.0.1", - "@capacitor/core": "^8.4.1", - "@capacitor/device": "^8.0.2", + "@capacitor/core": "^8.4.2", + "@capacitor/device": "^8.0.3", "@capacitor/filesystem": "^8.1.2", "@capacitor/geolocation": "^8.2.0", - "@capacitor/ios": "^8.4.1", - "@capacitor/local-notifications": "^8.2.0", + "@capacitor/ios": "^8.4.2", + "@capacitor/local-notifications": "^8.2.1", "@capacitor/network": "^8.0.1", "@capacitor/preferences": "^8.0.1", - "@capacitor/push-notifications": "^8.1.1", + "@capacitor/push-notifications": "^8.1.2", "@capacitor/share": "^8.0.1", - "@capacitor/splash-screen": "^8.0.1", + "@capacitor/splash-screen": "^8.0.2", "@capawesome/capacitor-android-edge-to-edge-support": "^8.0.8", - "@capgo/capacitor-social-login": "^8.3.35", - "@capgo/capacitor-wifi": "^8.4.0", - "@ionic/angular": "^8.8.13", + "@capgo/capacitor-social-login": "^8.3.37", + "@capgo/capacitor-wifi": "^8.4.1", + "@ionic/angular": "^8.8.14", "@ionic/core": "^8.7.17", "@ionic/pwa-elements": "^3.0.2", "@jsverse/transloco": "^8.4.0",