diff --git a/.github/actions/artifactory-oidc/action.yml b/.github/actions/artifactory-oidc/action.yml new file mode 100644 index 00000000..c41de0e1 --- /dev/null +++ b/.github/actions/artifactory-oidc/action.yml @@ -0,0 +1,71 @@ +name: 'Artifactory OIDC Authentication' +description: 'Exchange GitHub OIDC token for Artifactory credentials and configure Maven settings.xml' + +inputs: + artifactory_url: + description: 'Artifactory base URL (e.g. https://segment.jfrog.io)' + required: true + +outputs: + token: + description: 'Artifactory access token' + value: ${{ steps.exchange.outputs.token }} + +runs: + using: 'composite' + steps: + - name: Get OIDC token + id: oidc + shell: bash + run: | + OIDC_TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ + "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=jfrog-github" | jq -r '.value') + echo "::add-mask::$OIDC_TOKEN" + echo "oidc_token=$OIDC_TOKEN" >> "$GITHUB_OUTPUT" + + - name: Exchange OIDC token for Artifactory token + id: exchange + shell: bash + env: + ARTIFACTORY_URL: ${{ inputs.artifactory_url }} + run: | + HOST=$(echo "$ARTIFACTORY_URL" | sed 's|https://||') + ART_TOKEN=$(curl -s -X POST \ + "$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\": \"${{ steps.oidc.outputs.oidc_token }}\", \"subject_token_type\": \"urn:ietf:params:oauth:token-type:id_token\", \"provider_name\": \"github\"}" \ + | jq -r '.access_token') + echo "::add-mask::$ART_TOKEN" + echo "token=$ART_TOKEN" >> "$GITHUB_OUTPUT" + echo "host=$HOST" >> "$GITHUB_OUTPUT" + + - name: Write Maven settings.xml + shell: bash + env: + ART_TOKEN: ${{ steps.exchange.outputs.token }} + ART_HOST: ${{ steps.exchange.outputs.host }} + ARTIFACTORY_URL: ${{ inputs.artifactory_url }} + run: | + mkdir -p ~/.m2 + cat > ~/.m2/settings.xml << 'EOF' + + + + artifactory + central + __ARTIFACTORY_URL__/artifactory/virtual-maven-thirdparty + + + + + artifactory + _ + __ART_TOKEN__ + + + + EOF + sed -i "s|__ARTIFACTORY_URL__|${ARTIFACTORY_URL}|g" ~/.m2/settings.xml + sed -i "s|__ART_TOKEN__|${ART_TOKEN}|g" ~/.m2/settings.xml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..e484483a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,98 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +permissions: + id-token: write + contents: read + +env: + ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} + +jobs: + lint: + name: Lint (spotless + animal-sniffer) + runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubuntu-x64' }} + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Set up JDK 11 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'temurin' + java-version: '11' + cache: maven + + - name: Artifactory OIDC + if: ${{ !github.event.pull_request.head.repo.fork }} + uses: ./.github/actions/artifactory-oidc + with: + artifactory_url: ${{ vars.ARTIFACTORY_URL }} + + - name: Spotless check + run: mvn -B spotless:check + + - name: Animal Sniffer check + run: mvn -B animal-sniffer:check + + test: + name: Test (Java ${{ matrix.java-version }}) + runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubuntu-x64' }} + strategy: + fail-fast: false + matrix: + java-version: ['11', '17', '21'] + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Set up JDK ${{ matrix.java-version }} + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'temurin' + java-version: ${{ matrix.java-version }} + cache: maven + + - name: Artifactory OIDC + if: ${{ !github.event.pull_request.head.repo.fork }} + uses: ./.github/actions/artifactory-oidc + with: + artifactory_url: ${{ vars.ARTIFACTORY_URL }} + + - name: Run tests + run: mvn -B test + + build: + name: Build verification + runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubuntu-x64' }} + needs: [lint, test] + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Set up JDK 11 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'temurin' + java-version: '11' + cache: maven + + - name: Artifactory OIDC + if: ${{ !github.event.pull_request.head.repo.fork }} + uses: ./.github/actions/artifactory-oidc + with: + artifactory_url: ${{ vars.ARTIFACTORY_URL }} + + - name: Build + run: mvn -B package -DskipTests + + - name: Verify + run: mvn -B verify -DskipTests diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..2632436c --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,74 @@ +name: Deploy to Maven Central + +on: + release: + types: [published] + +permissions: + id-token: write + contents: read + +env: + ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} + +jobs: + test: + name: Pre-deploy tests + runs-on: ubuntu-x64 + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Set up JDK 11 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'temurin' + java-version: '11' + cache: maven + + - name: Artifactory OIDC + uses: ./.github/actions/artifactory-oidc + with: + artifactory_url: ${{ vars.ARTIFACTORY_URL }} + + - name: Run tests + run: mvn -B test + + deploy: + name: Deploy to Maven Central + runs-on: ubuntu-x64 + needs: [test] + environment: maven-central + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Set up JDK 11 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 + with: + distribution: 'temurin' + java-version: '11' + cache: maven + server-id: central + server-username: CI_DEPLOY_USERNAME + server-password: CI_DEPLOY_PASSWORD + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE + + - name: Artifactory OIDC + uses: ./.github/actions/artifactory-oidc + with: + artifactory_url: ${{ vars.ARTIFACTORY_URL }} + + - name: Deploy to Maven Central + env: + CI_DEPLOY_USERNAME: ${{ secrets.CI_DEPLOY_USERNAME }} + CI_DEPLOY_PASSWORD: ${{ secrets.CI_DEPLOY_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: | + mvn -B deploy \ + -DskipTests \ + -Dgpg.passphrase="$GPG_PASSPHRASE" \ + -P release diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index c59ec2cb..dd706a10 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -1,18 +1,12 @@ -# E2E Tests for analytics-java -# Copy this file to: analytics-java/.github/workflows/e2e-tests.yml -# -# This workflow: -# 1. Checks out the SDK and sdk-e2e-tests repos -# 2. Builds the SDK and e2e-cli -# 3. Runs the e2e test suite - name: E2E Tests on: push: - branches: [main, master] + branches: [master] pull_request: - branches: [main, master] + branches: [master] + schedule: + - cron: '0 6 * * 1-5' workflow_dispatch: inputs: e2e_tests_ref: @@ -20,47 +14,59 @@ on: required: false default: 'main' +permissions: + id-token: write + contents: read + +env: + ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} + jobs: e2e-tests: - # Skip on fork PRs where repo secrets aren't available - if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} - runs-on: ubuntu-latest + name: E2E Test Suite + if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }} + runs-on: ubuntu-x64 steps: - name: Checkout SDK - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: path: sdk - name: Checkout sdk-e2e-tests - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: repository: segmentio/sdk-e2e-tests ref: ${{ inputs.e2e_tests_ref || 'main' }} - token: ${{ secrets.E2E_TESTS_TOKEN }} path: sdk-e2e-tests - - name: Setup Java - uses: actions/setup-java@v4 + - name: Set up JDK 11 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 with: distribution: 'temurin' java-version: '11' + cache: maven + + - name: Artifactory OIDC + uses: ./sdk/.github/actions/artifactory-oidc + with: + artifactory_url: ${{ vars.ARTIFACTORY_URL }} - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4 with: node-version: '20' - name: Build Java SDK and e2e-cli working-directory: sdk - run: mvn package -pl e2e-cli -am -DskipTests + run: mvn -B package -pl e2e-cli -am -DskipTests - name: Find e2e-cli jar id: find-jar working-directory: sdk run: | JAR_PATH=$(find e2e-cli/target -name "e2e-cli-*-jar-with-dependencies.jar" | head -1) - echo "jar_path=$JAR_PATH" >> $GITHUB_OUTPUT + echo "jar_path=$JAR_PATH" >> "$GITHUB_OUTPUT" - name: Run E2E tests working-directory: sdk-e2e-tests @@ -71,7 +77,7 @@ jobs: - name: Upload test results if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: e2e-test-results path: sdk-e2e-tests/test-results/