This project belongs to the trends.earth project by Conservation International.
This repository implements the environment used for executing jobs run via the trends.earth API.
trends.earth-Environment/
├── gefcore/ # Core Python package
│ ├── __init__.py # Package initialization and main entry point
│ ├── api.py # API client for trends.earth-API
│ ├── loggers.py # Custom logging handlers
│ └── runner.py # Script execution engine
├── scripts/ # Utility scripts
│ └── dependency_manager.py # Security and dependency management
├── tests/ # Test suite
├── .github/workflows/ # CI/CD workflows
├── Dockerfile # Container build configuration
├── main.py # Application entry point
├── entrypoint.sh # Docker container entrypoint
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Development dependencies
├── pyproject.toml # Project configuration and tools
└── run_tests.sh # Test execution script
- trends.earth API - Backend API service
- trends.earth CLI - Command-line interface
This environment package serves as the execution platform for custom geospatial analysis scripts developed using the trends.earth CLI. Here's how to create and deploy new scripts:
Custom scripts are organized as packages with the following structure:
my-custom-script/
├── configuration.json # Script metadata and configuration
├── requirements.txt # Python dependencies specific to this script
└── src/ # Source code directory
├── __init__.py # Python package initialization
└── main.py # Main script entry point with run() function
Every script must implement a run(params, logger)
function in src/main.py
:
def run(params, logger):
"""
Main script execution function.
Args:
params (dict): Parameters passed from the API/UI
logger: Pre-configured logger instance for progress reporting
Returns:
dict: Results to be sent back to the API
"""
# Your script logic here
logger.info("Script started")
# Access input parameters
area_of_interest = params.get('geometry')
start_date = params.get('start_date')
end_date = params.get('end_date')
# Your analysis logic using Google Earth Engine, NumPy, etc.
result = perform_analysis(area_of_interest, start_date, end_date)
logger.info("Analysis complete")
return {
'status': 'success',
'results': result
}
The configuration.json
file defines script metadata and environment requirements:
{
"name": "sdg-15-3-1-indicator 2_1_17",
"environment": "trends.earth-environment",
"environment_version": "2.1.18"
}
Required fields:
name
- Unique identifier for your scriptenvironment
- Must be "trends.earth-environment"environment_version
- Version of this environment package to use
Important: The environment package is pulled from the main Docker registry (conservationinternational organization). The specified version must be built and publicly available in the registry before scripts can reference it. Check Docker Hub for available versions.
Server-assigned fields:
id
- Unique UUID assigned by the server when the script is published (do not include in initial submission)
Note: When first submitting a script, do not include the id
field in your configuration.json. The server will assign a unique UUID and return it in the response when the script is successfully published.
Script parameters are passed via the params
argument to your run()
function and are defined through the trends.earth UI or API rather than in the configuration file. Common parameters include:
geometry
- GeoJSON area of intereststart_date
/end_date
- Date ranges for analysisresolution
- Spatial resolution for analysis- Custom parameters specific to your analysis
Scripts running in this environment have access to:
- Google Earth Engine - Pre-authenticated and initialized
- Standard Python libraries - NumPy, SciPy, etc. (via base requirements)
- GDAL - Geospatial Data Abstraction Library (via Docker base image)
- Additional geospatial libraries - Can be added via your script's
requirements.txt
(Rasterio, Shapely, Fiona, etc.) - Custom logger - Integrated with trends.earth API for progress tracking
- Parameter retrieval - Automatic parameter loading from API (implemented via S3)
- Result publishing - Automatic result upload to API
Note: The base environment includes essential libraries for geospatial analysis. For additional Python packages, add them to your script's requirements.txt
file and they will be automatically installed when your script runs.
import numpy as np
def run(params, logger):
logger.info("Starting NumPy analysis")
data = np.array(params.get('input_data', []))
result = np.mean(data)
logger.info(f"Calculated mean: {result}")
return {'mean': result}
import ee
def run(params, logger):
logger.info("Starting GEE analysis")
# Get area of interest
geometry = ee.Geometry(params['geometry'])
# Load satellite data
collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
.filterBounds(geometry) \
.filterDate(params['start_date'], params['end_date'])
# Perform analysis
mean_image = collection.mean()
# Extract statistics
stats = mean_image.reduceRegion(
reducer=ee.Reducer.mean(),
geometry=geometry,
scale=30
).getInfo()
logger.info("Analysis complete")
return {'statistics': stats}
-
Create script package using trends.earth CLI:
tecli create my-script cd my-script
-
Develop your script in
src/main.py
with the requiredrun()
function -
Test locally using trends.earth CLI:
# Test with mock parameters (using query parameters) tecli start --param="geometry={...}&start_date=2023-01-01" # Test with a JSON payload file echo '{"geometry": {...}, "start_date": "2023-01-01", "end_date": "2023-12-31"}' > test_params.json tecli start --payload=test_params.json
-
Publish to API using CLI:
tecli publish my-script
-
Execute via API - The script will run in this environment container
- Error handling - Use try/except blocks and log errors appropriately
- Progress reporting - Use
logger.info()
for user-visible progress updates - Memory management - Be mindful of memory usage for large datasets
- Timeouts - Design scripts to complete within reasonable timeframes
- Parameter validation - Validate input parameters before processing
- Modular code - Split complex logic into separate functions/modules
- Python 3.10+
- Docker (for containerized development)
- Google Earth Engine service account (for production use)
-
Clone the repository:
git clone https://github.com/ConservationInternational/trends.earth-Environment.git cd trends.earth-Environment
-
Create and activate virtual environment:
python -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate
-
Install dependencies:
pip install -r requirements.txt pip install -r requirements-dev.txt
-
Run tests:
./run_tests.sh # Or directly with pytest pytest tests/ -v
-
Build the container:
docker build -t trends-earth-env .
-
Run the container:
docker run --rm \ -e ENV=development \ -e TESTING=false \ trends-earth-env
Required environment variables for production use:
ENV
- Environment mode (production
,staging
,development
,test
)TESTING
- Set totrue
for test environmentsROLLBAR_SCRIPT_TOKEN
- Rollbar error reporting tokenGOOGLE_PROJECT_ID
- Google Cloud Project IDGEE_ENDPOINT
- Google Earth Engine API endpointAPI_URL
- trends.earth API base URLAPI_USER
- API authentication usernameAPI_PASSWORD
- API authentication passwordEXECUTION_ID
- Unique execution identifierPARAMS_S3_BUCKET
- S3 bucket for parametersPARAMS_S3_PREFIX
- S3 key prefix for parameters
The project includes comprehensive testing with pytest:
# Run all tests
./run_tests.sh
# Run specific test files
pytest tests/test_api.py -v
# Run with coverage
pytest tests/ --cov=gefcore --cov-report=html
# Run only fast tests (exclude slow integration tests)
pytest tests/ -m "not slow"
Code quality is maintained using:
- Ruff - Fast Python linter and formatter
- mypy - Static type checking
- pytest - Testing framework with 92%+ coverage requirement
Run quality checks:
# Linting and formatting
ruff check gefcore/ tests/
ruff format gefcore/ tests/
# Type checking
mypy gefcore/ --ignore-missing-imports
Use the dependency manager script for security checks:
# Check for vulnerabilities
python scripts/dependency_manager.py --check-vulns
# Check for outdated packages
python scripts/dependency_manager.py --check-outdated
# Run comprehensive security audit
python scripts/dependency_manager.py --audit
# Run all security checks
python scripts/dependency_manager.py --all
# Install security tools
pip install safety bandit[toml]
# Check dependencies for vulnerabilities
safety scan -r requirements.txt
# Scan code for security issues
bandit -r gefcore/
gefcore.api
- HTTP client for communicating with trends.earth-API, handles authentication, retries, and error handlinggefcore.runner
- Main script execution engine that initializes Google Earth Engine and executes user scriptsgefcore.loggers
- Custom logging handlers that send logs to the API and handle different environment configurationsscripts.dependency_manager
- Security and dependency management utilities
- Container starts via
main.py
→gefcore.__init__.py
- Environment validation and logger setup
- Google Earth Engine authentication and initialization
- Script parameter retrieval from S3
- User script execution with monitoring and logging
- Results and status reporting back to API
docker run --rm -v $(pwd):/workspace aquasec/trivy fs /workspace
## Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes and add tests
4. Run the test suite (`./run_tests.sh`)
5. Ensure code quality checks pass
6. Commit your changes (`git commit -m 'Add amazing feature'`)
7. Push to the branch (`git push origin feature/amazing-feature`)
8. Open a Pull Request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.