feat(sso): Add SSO/OIDC authentication support with Vault/OpenBao integration #78
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize] | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| name: Run End-to-End Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Setup env via sstart | |
| uses: dirathea/setup-sstart-env@main | |
| env: | |
| INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET }} | |
| INFISICAL_UNIVERSAL_AUTH_CLIENT_ID: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID }} | |
| INFISICAL_SITE_URL: ${{ secrets.INFISICAL_SITE_URL }} | |
| with: | |
| config: | | |
| providers: | |
| - kind: infisical | |
| project_id: 8aded323-e110-4f48-9c7f-24c275358609 | |
| environment: prod | |
| path: /github | |
| - name: Authenticate to Google Cloud | |
| uses: google-github-actions/auth@v2 | |
| with: | |
| credentials_json: ${{ env.GOOGLE_APPLICATION_CREDENTIALS }} | |
| - name: Set up Cloud SDK | |
| uses: google-github-actions/setup-gcloud@v2 | |
| - name: Install Bitwarden CLI | |
| run: | | |
| BW_DOWNLOAD_URL=$(curl -s https://api.github.com/repos/bitwarden/cli/releases/latest | grep '"browser_download_url".*linux.*zip' | head -1 | sed -E 's/.*"([^"]+)".*/\1/') | |
| curl -L "${BW_DOWNLOAD_URL}" -o bw.zip | |
| unzip -q bw.zip | |
| chmod +x bw | |
| sudo mv bw /usr/local/bin/ | |
| rm bw.zip | |
| bw --version | |
| - name: Determine which tests to run | |
| id: test_filter | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| try { | |
| const { data: files } = await github.rest.pulls.listFiles({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.issue.number, | |
| }); | |
| const changedFiles = files.map(f => f.filename); | |
| console.log('Changed files:', changedFiles); | |
| // Map provider directories to test name prefixes | |
| const providerTestMap = { | |
| 'internal/provider/aws/': ['TestE2E_AWSSecretsManager'], | |
| 'internal/provider/azurekeyvault/': ['TestE2E_AzureKeyVault'], | |
| 'internal/provider/bitwarden/': ['TestE2E_Bitwarden', 'TestE2E_BitwardenSM'], | |
| 'internal/provider/doppler/': ['TestE2E_Doppler'], | |
| 'internal/provider/gcsm/': ['TestE2E_GCSM'], | |
| 'internal/provider/infisical/': ['TestE2E_Infisical'], | |
| 'internal/provider/onepassword/': ['TestE2E_OnePassword'], | |
| 'internal/provider/vault/': ['TestE2E_Vault', 'TestE2E_OpenBao'], | |
| 'internal/oidc/': ['TestE2E_SSO'], | |
| }; | |
| // Core files that require all tests | |
| const corePaths = [ | |
| 'internal/secrets/', | |
| 'internal/config/', | |
| 'internal/app/', | |
| 'internal/cli/', | |
| 'tests/end2end/', | |
| 'cmd/', | |
| ]; | |
| // Check if any core files changed | |
| const hasCoreChanges = changedFiles.some(file => | |
| corePaths.some(path => file.startsWith(path)) | |
| ); | |
| if (hasCoreChanges) { | |
| console.log('Core files changed, running all tests'); | |
| core.setOutput('test_filter', ''); | |
| core.setOutput('run_all_tests', 'true'); | |
| core.setOutput('skip_tests', 'false'); | |
| return; | |
| } | |
| // Find which providers changed | |
| const affectedTests = new Set(); | |
| for (const file of changedFiles) { | |
| for (const [providerPath, testNames] of Object.entries(providerTestMap)) { | |
| if (file.startsWith(providerPath)) { | |
| testNames.forEach(test => affectedTests.add(test)); | |
| } | |
| } | |
| } | |
| if (affectedTests.size === 0) { | |
| console.log('No provider changes detected, skipping end2end tests'); | |
| core.setOutput('test_filter', ''); | |
| core.setOutput('run_all_tests', 'false'); | |
| core.setOutput('skip_tests', 'true'); | |
| return; | |
| } | |
| // Construct test filter regex (matches any of the affected tests) | |
| // Format: TestE2E_(Provider1|Provider2) for go test -run flag | |
| const testFilter = Array.from(affectedTests).join('|'); | |
| console.log('Running selective tests:', testFilter); | |
| core.setOutput('test_filter', testFilter); | |
| core.setOutput('run_all_tests', 'false'); | |
| core.setOutput('skip_tests', 'false'); | |
| } catch (error) { | |
| console.log('Error determining test filter, running all tests:', error.message); | |
| core.setOutput('test_filter', ''); | |
| core.setOutput('run_all_tests', 'true'); | |
| core.setOutput('skip_tests', 'false'); | |
| } | |
| - name: Run end-to-end tests | |
| if: steps.test_filter.outputs.skip_tests != 'true' | |
| env: | |
| CGO_LDFLAGS: -lm | |
| # the rest of env supplied by setup-sstart-env | |
| run: | | |
| if [ "${{ steps.test_filter.outputs.run_all_tests }}" = "true" ]; then | |
| echo "Running all end-to-end tests" | |
| go test -v ./tests/end2end/... | |
| else | |
| echo "Running selective tests: ${{ steps.test_filter.outputs.test_filter }}" | |
| go test -v -run "${{ steps.test_filter.outputs.test_filter }}" ./tests/end2end/... | |
| fi | |
| - name: Skip end-to-end tests | |
| if: steps.test_filter.outputs.skip_tests == 'true' | |
| run: | | |
| echo "No provider changes detected. Skipping end-to-end tests." | |
| build: | |
| name: Build | |
| strategy: | |
| matrix: | |
| include: | |
| - goos: linux | |
| goarch: amd64 | |
| runner: ubuntu-latest | |
| - goos: linux | |
| goarch: arm64 | |
| runner: ubuntu-latest | |
| - goos: darwin | |
| goarch: amd64 | |
| runner: macos-latest | |
| - goos: darwin | |
| goarch: arm64 | |
| runner: macos-latest | |
| - goos: windows | |
| goarch: amd64 | |
| runner: windows-latest | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Install Linux ARM64 cross-compilation toolchain (Linux ARM64 only) | |
| if: matrix.goos == 'linux' && matrix.goarch == 'arm64' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu | |
| echo "CC=aarch64-linux-gnu-gcc" >> $GITHUB_ENV | |
| echo "CXX=aarch64-linux-gnu-g++" >> $GITHUB_ENV | |
| echo "AR=aarch64-linux-gnu-ar" >> $GITHUB_ENV | |
| echo "AS=aarch64-linux-gnu-as" >> $GITHUB_ENV | |
| - name: Build binary | |
| env: | |
| CGO_ENABLED: 1 | |
| CGO_LDFLAGS: -lm | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| run: | | |
| go build -ldflags="-s -w -X github.com/dirathea/sstart/internal/cli.version=snapshot -X github.com/dirathea/sstart/internal/cli.commit=${{ github.sha }} -X github.com/dirathea/sstart/internal/cli.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" -o sstart${{ matrix.goos == 'windows' && '.exe' || '' }} ./cmd/sstart | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sstart-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.goos == 'windows' && '.exe' || '' }} | |
| path: sstart${{ matrix.goos == 'windows' && '.exe' || '' }} | |
| retention-days: 1 | |