diff --git a/.github/actions/lakebase-project-delete/action.yml b/.github/actions/lakebase-project-delete/action.yml new file mode 100644 index 0000000000..5166d93cce --- /dev/null +++ b/.github/actions/lakebase-project-delete/action.yml @@ -0,0 +1,39 @@ +name: 'Delete Neon Project' +description: 'Delete Neon Project using API' + +inputs: + curl_authorization_options: + description: 'Curl authorization options - e.g. --header "Authorization: Bearer "' + required: true + org_id: + description: 'Organization ID, required' + required: true + api_host: + description: 'Lakebase API host, e.g. dbc-55e65913-66de.dev.databricks.com/ajax-api/2.0/lakebase-console' + required: true + project_id: + description: 'ID of the Project to delete' + required: true + +runs: + using: "composite" + steps: + - name: Delete Lakebase Project + # Do not try to delete a project if .github/actions/neon-project-create failed before + if: ${{ inputs.project_id != '' }} + shell: bash -euxo pipefail {0} + run: | + curl \ + "https://${API_HOST}/api/v2/projects/${PROJECT_ID}" \ + --fail \ + --request DELETE \ + --header "Accept: application/json" \ + --header "Content-Type: application/json" \ + ${CURL_AUTH} + + echo "Project ${PROJECT_ID} has been deleted" + env: + API_HOST: ${{ inputs.api_host }} + CURL_AUTH: ${{ inputs.curl_authorization_options }} + ORG_ID: ${{ inputs.org_id }} + PROJECT_ID: ${{ inputs.project_id }} diff --git a/.github/actions/lakebase_create_token/action.yml b/.github/actions/lakebase_create_token/action.yml new file mode 100644 index 0000000000..34cdebf899 --- /dev/null +++ b/.github/actions/lakebase_create_token/action.yml @@ -0,0 +1,73 @@ +name: 'Create Lakebase Bearer Token' +description: 'Generate a short-lived bearer token from OAuth credentials' + +inputs: + client_id: + description: 'OAuth client ID' + required: true + client_secret: + description: 'OAuth client secret' + required: true + oidc_host: + description: 'OIDC host URL' + required: false + default: 'https://dbc-55e65913-66de.dev.databricks.com' + +outputs: + lakebase_bearer_token: + description: 'Generated bearer access token' + value: ${{ steps.create-bearer-token.outputs.lakebase_bearer_token }} + +runs: + using: "composite" + steps: + - name: Create Bearer Token + id: create-bearer-token + # A shell without `set -x` to not expose secrets in logs + shell: bash -euo pipefail {0} + run: | + res=$(curl -X POST "${OIDC_HOST}/oidc/v1/token" \ + -w "%{http_code}" \ + --header "Content-Type: application/x-www-form-urlencoded" \ + --data "grant_type=client_credentials" \ + --data "client_id=${CLIENT_ID}" \ + --data "client_secret=${CLIENT_SECRET}" \ + --data "scope=all-apis") + + code=${res: -3} + if [[ ${code} -ge 400 ]]; then + echo "Token request failed with error code ${code}" + echo ${res::-3} + exit 1 + else + response=${res::-3} + fi + + # Extract access token from JSON response + access_token=$(echo "$response" | jq --raw-output '.access_token') + + if [[ "$access_token" == "null" || -z "$access_token" ]]; then + echo "Failed to extract access token from response" + exit 1 + fi + + # Extract token lifetime + expires_in=$(echo "$response" | jq --raw-output '.expires_in') + + # Mask the token to prevent it from appearing in logs + echo "::add-mask::${access_token}" + + # Set the token as output + echo "lakebase_bearer_token=${access_token}" >> $GITHUB_OUTPUT + + # Log token lifetime + if [[ "$expires_in" != "null" && -n "$expires_in" ]]; then + echo "Bearer token generated successfully (expires in ${expires_in} seconds)" + else + echo "Bearer token generated successfully" + fi + + env: + CLIENT_ID: ${{ inputs.client_id }} + CLIENT_SECRET: ${{ inputs.client_secret }} + OIDC_HOST: ${{ inputs.oidc_host }}