|
1 | 1 | # ee-initialize-github-actions |
2 | | -Instructions for initializing to Earth Engine in Python scripts run with GitHub Actions |
| 2 | +_Instructions for initializing to Earth Engine in Python scripts run with GitHub Actions. There |
| 3 | +are multiple ways to do this, I'd like to add several, but for now it demonstrates constructing |
| 4 | +credentials from `google.oauth2.credentials.Credentials`_ |
| 5 | + |
| 6 | +So you want to test Earth Engine in your GitHub Actions? Great idea! To do it, you'll need |
| 7 | +to authenticate and initialize to the Earth Engine service. This repo describes how to |
| 8 | +generate a credentials file, save those credentials as a GitHub Secret, construct |
| 9 | +oauth2 credentials and pass them to `ee.Initialize()`. A basic workflow file and Earth |
| 10 | +Engine script are provided, but they are super minimal and not the focus of this demo. |
| 11 | + |
| 12 | +## 1. Create Earth Engine credentials |
| 13 | + |
| 14 | +**Install the latest version of `earthengine-api`**. Activate your development |
| 15 | +environment and update the library. (I'm using micromamba for package management) |
| 16 | + |
| 17 | +```shell |
| 18 | +micromamba activate ee |
| 19 | +micromamba install conda-forge::earthengine-api |
| 20 | +``` |
| 21 | + |
| 22 | +**Authenticate to create a credentials file.** Run the |
| 23 | +[`earthengine authenticate`](https://developers.google.com/earth-engine/guides/command_line#authenticate) |
| 24 | +command. Use `--force` to ensure that the auth flow is triggered and new credentials are |
| 25 | +written. If a browser is detected, it'll have you go online to complete authentication; |
| 26 | +follow the prompts. If a browser is not available, see |
| 27 | +[alternatives]([url](https://developers.google.com/earth-engine/guides/auth#authentication_details)). |
| 28 | + |
| 29 | +```shell |
| 30 | +earthengine authenticate --force |
| 31 | +``` |
| 32 | + |
| 33 | +The credentials file will be written to `~/.config/earthengine/credentials`. It is meant to be |
| 34 | +private, don't share it or people can use your Earth Engine resources. |
| 35 | + |
| 36 | +**Add a cloud project to the credentials file.** All Earth Engine requests are routed through |
| 37 | +Google Cloud projects. You'll need to specify a project when you initialize to Earth Engine services. |
| 38 | +One way to do that is to include a default project in your credentials file. Here we add one using the |
| 39 | +`earthengine set_project` command. Be sure to edit the project ID to one that you want associated |
| 40 | +with running tests in your GitHub repo. |
| 41 | + |
| 42 | +```shell |
| 43 | +earthengine authenticate --force <YOUR-PROJECT-ID> |
| 44 | +``` |
| 45 | + |
| 46 | +The given project will now appear in the credentials file just created. |
| 47 | + |
| 48 | +## 2. Add the credentials information as a GitHub secret |
| 49 | + |
| 50 | +**Find your credentials file (`~/.config/earthengine/credentials`) and open it with a text editor.** |
| 51 | +If should be single-line JSON formatted like this: |
| 52 | + |
| 53 | +```json |
| 54 | +{"client_id": "value", "client_secret": "value", "refresh_token": "value", "project": "value"} |
| 55 | +``` |
| 56 | + |
| 57 | +**Go to the GitHub repo where you're running GitHub Actions and create a new |
| 58 | +[repository secret](https://docs.github.com/en/codespaces/managing-codespaces-for-your-organization/managing-development-environment-secrets-for-your-repository-or-organization).** |
| 59 | +On the top tabs click "Actions", on the left TOC click "Secrets and variables", select "Actions", |
| 60 | +and then "New repository secret" |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +You'll be prompted to name the secret; I suggest `EARTHENGINE_TOKEN`. Copy the credentials information |
| 65 | +from your text editor into the secret input text box. It's important that the text be unaltered and |
| 66 | +unformatted to avoid JSON decoding errors. |
| 67 | + |
| 68 | +> We advise minifying your JSON into a single line string before storing it in a GitHub Secret. When a |
| 69 | +> GitHub Secret is used in a GitHub Actions workflow, each line of the secret is masked in log output. |
| 70 | +> This can lead to aggressive sanitization of benign characters like curly braces ({}) and brackets ([]). |
| 71 | +
|
| 72 | +## 3. Write your workflow and add the EARTHENGINE_TOKEN secret as an environmental varible |
| 73 | + |
| 74 | +I'll not get into the [details of writing a workflow](https://docs.github.com/en/actions/writing-workflows/about-workflows). |
| 75 | +You can [see my full example](https://github.com/gee-community/ee-initialize-github-actions/blob/main/.github/workflows/ee-test-with-oauth2.yml), |
| 76 | +but **the important part to note is that I'm setting an environmental variable from the credentials secret |
| 77 | +in the step that runs my Earth Engine script** (ee-test-with-oauth2.py). |
| 78 | + |
| 79 | +```yml |
| 80 | +- name: Run Earth Engine Script |
| 81 | + env: |
| 82 | + EARTHENGINE_TOKEN: ${{ secrets.EARTHENGINE_TOKEN }} |
| 83 | + run: | |
| 84 | + python ee-test-with-oauth2.py |
| 85 | +``` |
| 86 | +
|
| 87 | +## 4. Initialize to Earth Engine in your test file |
| 88 | +
|
| 89 | +In the test file that makes Earth Engine requests, **construct Oauth2 credentials |
| 90 | +from the credentials info in the secret**. The credentials info is fetched from |
| 91 | +the environment variable we set previously, and then arranged as arguments |
| 92 | +to `google.oauth2.credentials.Credentials` whose result is given to `ee.Initialize()`. |
| 93 | + |
| 94 | +``` |
| 95 | +import ee |
| 96 | +import json |
| 97 | +import os |
| 98 | +import google.oauth2.credentials |
| 99 | + |
| 100 | +stored = json.loads(os.getenv("EARTHENGINE_TOKEN")) |
| 101 | +credentials = google.oauth2.credentials.Credentials( |
| 102 | + None, |
| 103 | + token_uri="https://oauth2.googleapis.com/token", |
| 104 | + client_id=stored["client_id"], |
| 105 | + client_secret=stored["client_secret"], |
| 106 | + refresh_token=stored["refresh_token"], |
| 107 | + quota_project_id=stored["project"], |
| 108 | +) |
| 109 | + |
| 110 | +ee.Initialize(credentials=credentials) |
| 111 | + |
| 112 | +print(ee.String("Greetings from the Earth Engine servers!").getInfo()) |
| 113 | +``` |
| 114 | +
|
| 115 | +## 5. Test the script |
| 116 | +
|
| 117 | +In this case, I'm just **manually triggering the workflow from the "Actions" tab, |
| 118 | +clicking on the workflow and running the workflow**. |
| 119 | +
|
| 120 | + |
| 121 | +
|
| 122 | +As you can see the scripts runs successfully and we get a nice message from the |
| 123 | +Earth Engine servers 😁 |
| 124 | +
|
| 125 | + |
| 126 | +
|
| 127 | +
|
| 128 | +
|
| 129 | +
|
| 130 | +
|
| 131 | +
|
| 132 | +
|
0 commit comments