diff --git a/.github/actions/artifactory-oidc/action.yml b/.github/actions/artifactory-oidc/action.yml new file mode 100644 index 0000000..23a5391 --- /dev/null +++ b/.github/actions/artifactory-oidc/action.yml @@ -0,0 +1,71 @@ +name: "Artifactory OIDC Auth" +description: "Exchange GitHub OIDC token for Artifactory access token and configure pub" + +inputs: + artifactory-url: + description: "JFrog platform base URL. Falls back to ARTIFACTORY_URL env var." + required: false + default: "" + oidc-provider-name: + description: "OIDC provider name configured in Artifactory" + required: false + default: "github-actions-segmentio" + pub-repo: + description: "Artifactory virtual pub repository name" + required: false + default: "virtual-pub-thirdparty" + +runs: + using: "composite" + steps: + - name: Exchange GitHub OIDC token for Artifactory token + shell: bash + env: + INPUT_ARTIFACTORY_URL: ${{ inputs.artifactory-url }} + OIDC_PROVIDER_NAME: ${{ inputs.oidc-provider-name }} + PUB_REPO: ${{ inputs.pub-repo }} + run: | + set -euo pipefail + ARTIFACTORY_URL="${INPUT_ARTIFACTORY_URL:-${ARTIFACTORY_URL:-}}" + if [ -z "${ARTIFACTORY_URL}" ]; then + echo "::error::ARTIFACTORY_URL is not set (pass as input or set as env var)"; exit 1 + fi + + OIDC_JWT=$(curl -sS \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${ARTIFACTORY_URL}" \ + -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" | jq -r '.value') + + if [ -z "$OIDC_JWT" ] || [ "$OIDC_JWT" = "null" ]; then + echo "::error::Failed to obtain GitHub OIDC token"; exit 1 + fi + + decode_seg() { local s="${1}"; local m=$(( ${#s} % 4 )); [ $m -ne 0 ] && s="${s}$(printf '=%.0s' $(seq 1 $((4-m))))"; echo "$s" | tr '_-' '/+' | base64 -d 2>/dev/null; } + PAYLOAD=$(decode_seg "$(echo "$OIDC_JWT" | cut -d. -f2)") + echo "OIDC token claims:" + echo " sub = $(echo "$PAYLOAD" | jq -r '.sub')" + echo " aud = $(echo "$PAYLOAD" | jq -r '.aud')" + echo " iss = $(echo "$PAYLOAD" | jq -r '.iss')" + + RESP=$(curl -sS "${ARTIFACTORY_URL}/access/api/v1/oidc/token" \ + -H 'Content-Type: application/json' \ + -d "{\"grant_type\":\"urn:ietf:params:oauth:grant-type:token-exchange\", + \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", + \"subject_token\":\"${OIDC_JWT}\", + \"provider_name\":\"${OIDC_PROVIDER_NAME}\"}") + + ART_TOKEN=$(echo "$RESP" | jq -r '.access_token // empty') + + if [ -z "$ART_TOKEN" ]; then + echo "::error::OIDC token exchange failed." + echo "$RESP" | jq 'walk(if type == "object" then with_entries(if (.key | test("token"; "i")) then .value = "" else . end) else . end)' 2>/dev/null \ + || echo "::error::(response withheld — not valid JSON)" + exit 1 + fi + echo "::add-mask::$ART_TOKEN" + + HOST=$(echo "${ARTIFACTORY_URL}" | sed -E 's#^https?://##') + PUB_HOSTED_URL="https://:${ART_TOKEN}@${HOST}/artifactory/api/pub/${PUB_REPO}" + + echo "::add-mask::${PUB_HOSTED_URL}" + echo "PUB_HOSTED_URL=${PUB_HOSTED_URL}" >> "$GITHUB_ENV" + echo "Configured pub to resolve through Artifactory (${PUB_REPO})" diff --git a/.github/workflows/analytics_flutter.yml b/.github/workflows/analytics_flutter.yml deleted file mode 100644 index ccfd2dc..0000000 --- a/.github/workflows/analytics_flutter.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Analytics Flutter Test Code - -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - build_and_test: - name: Run Test - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: "13.0.13+5" - - - uses: subosito/flutter-action@v2 - with: - channel: stable - flutter-version: 3.29.2 - - - name: Get dependencies - run: cd packages/core && flutter pub get - - - name: Analyze Dart code - run: cd packages/core && flutter analyze - - - name: Run unit tests - run: cd packages/core && flutter test --coverage - - - name: Upload coverage to codecov - run: curl -s https://codecov.io/bash - shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f0c01a5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,73 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + id-token: write + contents: read + +env: + ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} + +jobs: + test: + name: Test - ${{ matrix.package }} + runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubuntu-x64' }} + strategy: + fail-fast: false + matrix: + package: + - core + - plugins/plugin_adjust + - plugins/plugin_advertising_id + - plugins/plugin_amplitude + - plugins/plugin_appsflyer + - plugins/plugin_firebase + - plugins/plugin_idfa + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'zulu' + java-version: '17' + + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 + with: + channel: stable + flutter-version: 3.29.2 + + - name: Authenticate with Artifactory + if: ${{ !github.event.pull_request.head.repo.fork }} + uses: ./.github/actions/artifactory-oidc + + - name: Get dependencies + run: flutter pub get + working-directory: packages/${{ matrix.package }} + + - name: Analyze + run: flutter analyze + working-directory: packages/${{ matrix.package }} + + - name: Run tests + run: flutter test --coverage + working-directory: packages/${{ matrix.package }} + + all-checks: + name: All Checks Passed + needs: [test] + runs-on: ubuntu-latest + if: always() + steps: + - name: Check all job statuses + run: | + if [ "${{ needs.test.result }}" != "success" ]; then + echo "One or more checks failed" + exit 1 + fi diff --git a/.github/workflows/create_jira.yml b/.github/workflows/create_jira.yml deleted file mode 100644 index 8180ac0..0000000 --- a/.github/workflows/create_jira.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Create Jira Ticket - -on: - issues: - types: - - opened - -jobs: - create_jira: - name: Create Jira Ticket - runs-on: ubuntu-latest - environment: IssueTracker - steps: - - name: Checkout - uses: actions/checkout@master - - name: Login - uses: atlassian/gajira-login@master - env: - JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} - JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} - JIRA_API_TOKEN: ${{ secrets.JIRA_TOKEN }} - JIRA_EPIC_KEY: ${{ secrets.JIRA_EPIC_KEY }} - JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }} - - - name: Create - id: create - uses: atlassian/gajira-create@master - with: - project: ${{ secrets.JIRA_PROJECT }} - issuetype: Bug - summary: | - [${{ github.event.repository.name }}] (${{ github.event.issue.number }}): ${{ github.event.issue.title }} - description: | - Github Link: ${{ github.event.issue.html_url }} - ${{ github.event.issue.body }} - fields: '{"parent": {"key": "${{ secrets.JIRA_EPIC_KEY }}"}}' - - - name: Log created issue - run: echo "Issue ${{ steps.create.outputs.issue }} was created" \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..4048d7f --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,65 @@ +name: Publish to pub.dev + +on: + release: + types: [published] + workflow_dispatch: + inputs: + package: + description: "Package to publish (e.g. core, plugins/plugin_firebase)" + required: true + default: "core" + +permissions: + id-token: write + contents: read + +env: + ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} + +jobs: + test: + name: Pre-publish tests + runs-on: ubuntu-x64 + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'zulu' + java-version: '17' + + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 + with: + channel: stable + flutter-version: 3.29.2 + + - name: Authenticate with Artifactory + uses: ./.github/actions/artifactory-oidc + + - name: Get dependencies + run: flutter pub get + working-directory: packages/${{ github.event.inputs.package || 'core' }} + + - name: Run tests + run: flutter test + working-directory: packages/${{ github.event.inputs.package || 'core' }} + + publish: + name: Publish to pub.dev + runs-on: ubuntu-x64 + needs: [test] + environment: production + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2 + with: + channel: stable + flutter-version: 3.29.2 + + - name: Publish to pub.dev (Trusted Publishing) + run: dart pub publish --force + working-directory: packages/${{ github.event.inputs.package || 'core' }}