Skip to content

Commit f3ca7fe

Browse files
authored
Upgrade Airflow content to 2.11.0. (#187)
* Upgrade Airflow content to 2.11.0. This must only be merged into `master` when actual Airflow 2.11 is already running in production, not before. Part of https://dfinity.atlassian.net/browse/DRE-496 . * Fix build pipeline.
1 parent f9a420b commit f3ca7fe

6 files changed

Lines changed: 72 additions & 35 deletions

File tree

.github/workflows/test/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ runs:
88
id: prep
99
run: |
1010
ret=0
11-
out=$(make venv/bin venv/bin/mypy venv/bin/ruff venv/bin/pytest venv/lib/*/site-packages/mock 2>&1) || ret=$?
11+
out=$(make airflow-setup venv/bin/mypy venv/bin/ruff venv/bin/pytest venv/lib/*/site-packages/mock 2>&1) || ret=$?
1212
if [ $ret != 0 ]
1313
then
1414
echo "$out" >&2

Makefile

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,51 @@
11
VENV_DIR = venv
2-
VENV_BINDIR = $(VENV_DIR)/bin
3-
.PHONY = test ruff mypy pytest
2+
VENV_BIN_DIR = $(VENV_DIR)/bin
3+
AIRFLOW_SETUP = $(VENV_BIN_DIR)/.airflow-2.11.0
4+
AIRFLOW_CFG = airflow/airflow.cfg
5+
AIRFLOW_TESTS_HOME = $(PWD)/tests
6+
AIRFLOW_TESTS_CFG = $(AIRFLOW_TESTS_HOME)/airflow.cfg
7+
AIRFLOW_TESTS_DB = $(AIRFLOW_TESTS_HOME)/airflow.db
48

5-
$(VENV_BINDIR):
9+
.PHONY = airflow-setup test ruff mypy pytest
10+
11+
$(AIRFLOW_CFG):
612
bin/airflow setup
7-
touch $(VENV_BINDIR)
813

9-
$(VENV_DIR)/lib/*/site-packages/mock: $(VENV_BINDIR)
10-
$(VENV_BINDIR)/pip3 install mock
14+
$(AIRFLOW_SETUP): $(AIRFLOW_CFG)
15+
touch $(AIRFLOW_SETUP)
16+
17+
airflow-setup: $(AIRFLOW_SETUP)
18+
19+
$(VENV_DIR)/lib/*/site-packages/mock: $(AIRFLOW_SETUP)
20+
$(VENV_BIN_DIR)/pip3 install mock
1121
touch $(VENV_DIR)/lib/*/site-packages/mock
1222

13-
$(VENV_BINDIR)/pytest: $(VENV_BINDIR)
14-
$(VENV_BINDIR)/pip3 install pytest pytest-mock
15-
touch $(VENV_BINDIR)/pytest
23+
$(VENV_BIN_DIR)/pytest: $(AIRFLOW_SETUP)
24+
$(VENV_BIN_DIR)/pip3 install pytest pytest-mock
25+
touch $(VENV_BIN_DIR)/pytest
26+
27+
$(VENV_BIN_DIR)/mypy: $(AIRFLOW_SETUP)
28+
$(VENV_BIN_DIR)/pip3 install mypy types-PyYAML types-requests types-mock
29+
touch $(VENV_BIN_DIR)/mypy
1630

17-
$(VENV_BINDIR)/mypy: $(VENV_BINDIR)
18-
$(VENV_BINDIR)/pip3 install mypy types-PyYAML types-requests types-mock
19-
touch $(VENV_BINDIR)/mypy
31+
$(VENV_BIN_DIR)/ruff: $(AIRFLOW_SETUP)
32+
$(VENV_BIN_DIR)/pip3 install ruff
33+
touch $(VENV_BIN_DIR)/ruff
2034

21-
$(VENV_BINDIR)/ruff: $(VENV_BINDIR)
22-
$(VENV_BINDIR)/pip3 install ruff
23-
touch $(VENV_BINDIR)/ruff
35+
mypy: $(VENV_BIN_DIR)/mypy
36+
PYTHONPATH=$(PWD)/plugins:$(PWD)/shared MYPY_PATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BIN_DIR)/mypy --config=mypy.ini
2437

25-
mypy: $(VENV_BINDIR)/mypy
26-
PYTHONPATH=$(PWD)/plugins:$(PWD)/shared MYPY_PATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BINDIR)/mypy --config=mypy.ini
38+
ruff: $(VENV_BIN_DIR)/ruff
39+
PYTHONPATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BIN_DIR)/ruff check shared plugins dags
2740

28-
ruff: $(VENV_BINDIR)/ruff
29-
PYTHONPATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BINDIR)/ruff check shared plugins dags
41+
$(AIRFLOW_TESTS_CFG): $(AIRFLOW_SETUP)
42+
mkdir -p $(AIRFLOW_TESTS_HOME)
43+
cp -f $(AIRFLOW_CFG) $(AIRFLOW_TESTS_CFG)
3044

31-
tests/airflow.db: $(VENV_BINDIR)
32-
AIRFLOW__DATABASE__LOAD_DEFAULT_CONNECTIONS=False AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW__CORE__UNIT_TEST_MODE=True AIRFLOW_HOME=$(PWD)/tests PYTHONPATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BINDIR)/airflow db migrate
45+
tests/airflow.db: $(AIRFLOW_SETUP) $(AIRFLOW_TESTS_CFG)
46+
AIRFLOW__CORE__EXECUTOR=SequentialExecutor AIRFLOW__DATABASE__LOAD_DEFAULT_CONNECTIONS=False AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW__CORE__UNIT_TEST_MODE=True AIRFLOW_HOME=$(AIRFLOW_TESTS_HOME) PYTHONPATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BIN_DIR)/airflow db migrate
3347

34-
pytest: tests/airflow.db $(VENV_BINDIR)/pytest $(VENV_DIR)/lib/*/site-packages/mock
35-
AIRFLOW__DATABASE__LOAD_DEFAULT_CONNECTIONS=False AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW__CORE__UNIT_TEST_MODE=True AIRFLOW__CORE__ALLOWED_DESERIALIZATION_CLASSES_REGEXP="(airflow|dfinity)[.].*" AIRFLOW_HOME=$(PWD)/tests PYTHONPATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BINDIR)/pytest -vv tests
48+
pytest: tests/airflow.db $(VENV_BIN_DIR)/pytest $(VENV_DIR)/lib/*/site-packages/mock
49+
AIRFLOW__CORE__EXECUTOR=SequentialExecutor AIRFLOW__DATABASE__LOAD_DEFAULT_CONNECTIONS=False AIRFLOW__CORE__LOAD_EXAMPLES=False AIRFLOW__CORE__UNIT_TEST_MODE=True AIRFLOW__CORE__ALLOWED_DESERIALIZATION_CLASSES_REGEXP="(airflow|dfinity)[.].*" AIRFLOW_HOME=$(PWD)/tests PYTHONPATH=$(PWD)/plugins:$(PWD)/shared $(VENV_BIN_DIR)/pytest -vv tests
3650

3751
test: ruff mypy pytest

bin/airflow

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ function setup_airflow_variables_and_connections() {
6060
"$AIRFLOW_BIN" connections add "github.node_allocation" --conn-type generic --conn-password "$NODE_ALLOC_PAT" --conn-description "Used by the target topology flow. Permits access to the https://github.com/dfinity/node_allocation repository."
6161
}
6262

63+
AIRFLOW_SETUP="$VENV_BIN_DIR"/.airflow-2.11.0
6364
if [ "$1" == "setup" ]
6465
then
65-
PYTHON_VERSION=$(python -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
66+
PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
6667

6768
# Split version
6869
PYTHON_MAJOR=$(echo "$PYTHON_VERSION" | cut -d. -f1)
@@ -73,12 +74,17 @@ then
7374
exit 1
7475
fi
7576

76-
python -m venv "$VENV_DIR"
77-
"$VENV_DIR"/bin/pip3 install "apache-airflow[celery]==2.9.1" \
77+
if [ "$PYTHON_MAJOR" -lt 3 ] || { [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 11 ]; }; then
78+
echo "❌ Python $PYTHON_VERSION is not supported. Please use Python 3.11 or higher."
79+
exit 1
80+
fi
81+
82+
python3 -m venv "$VENV_DIR"
83+
"$VENV_DIR"/bin/pip3 install "apache-airflow[celery]==2.11.0" \
7884
apache-airflow-providers-slack[common.sql] \
7985
apache-airflow-providers-google \
8086
"apache-airflow[amazon]" \
81-
--constraint https://raw.githubusercontent.com/apache/airflow/constraints-2.9.1/constraints-3.11.txt
87+
--constraint https://raw.githubusercontent.com/apache/airflow/constraints-2.11.0/constraints-$PYTHON_MAJOR.$PYTHON_MINOR.txt
8288
mkdir -p "$AIRFLOW_HOME"
8389
if ! test -f "$AIRFLOW_HOME"/airflow.db
8490
then
@@ -87,7 +93,9 @@ then
8793
PATH="$VENV_DIR/bin:$PATH" "$VENV_DIR"/bin/airflow db migrate
8894
fi
8995
pushd "$AIRFLOW_HOME"
96+
rm -f dags
9097
ln -sfT ../dags dags
98+
rm -f plugins
9199
ln -sfT ../plugins plugins
92100
sed -i 's/reload_on_plugin_change.*/reload_on_plugin_change = True/' airflow.cfg
93101
sed -i 's/load_examples.*/load_examples = False/' airflow.cfg
@@ -102,6 +110,8 @@ then
102110
else
103111
echo "Skipping Airflow variables and connections setup."
104112
fi
113+
114+
touch "$AIRFLOW_SETUP"
105115
fi
106116

107117
test -x "$VENV_DIR"/bin/airflow || {
@@ -114,6 +124,11 @@ test -f "$AIRFLOW_HOME"/airflow.cfg || {
114124
echo "Run this command with 'setup' as its only argument to initialize it." >&2
115125
exit 32
116126
}
127+
if ! test -f "$AIRFLOW_SETUP"
128+
then
129+
echo "Sorry, you have to upgrade your Airflow stack to 2.11.0. Run '$0 setup' to do so." >&2
130+
exit 48
131+
fi
117132

118133
if [ "$1" == "check-setup" ]
119134
then
@@ -126,6 +141,7 @@ then
126141
PATH="$VENV_DIR/bin:$PATH" "$VENV_DIR"/bin/airflow info >&2
127142
echo "You can now run this command with 'standalone' as its only argument." >&2
128143
echo "When you do that, note the admin password in the scrollback buffer -- you will need it to log in." >&2
144+
echo "Also, please exit any IDEs that have this project open, in order to cause it to refresh its Python configuration." >&2
129145
exit
130146
fi
131147

dags/test_dag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def finish() -> None:
5151
>> test_operator.TestTask(
5252
task_id="task_2",
5353
)
54-
>> TimeDeltaSensorAsync( # type: ignore
54+
>> TimeDeltaSensorAsync(
5555
task_id="wait_2_minutes",
5656
delta=datetime.timedelta(minutes=2),
5757
)

plugins/operators/gsheets_rollout.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ class GetFeatureRolloutPlan(GoogleSheetsCreateSpreadsheetOperator):
101101
def execute(self, context: Any) -> RolloutFeatures: # type: ignore
102102
hook = GSheetsHook(
103103
gcp_conn_id=self.gcp_conn_id,
104-
delegate_to=self.delegate_to,
105104
impersonation_chain=self.impersonation_chain,
106105
)
107106

plugins/sensors/ic_os_rollout.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import datetime
66
import itertools
77
import time
8-
from typing import Any, Sequence, TypedDict, cast
8+
from typing import Any, NoReturn, Sequence, TypedDict, cast
99

1010
import dfinity.dre as dre
1111
import dfinity.ic_types as ic_types
@@ -25,7 +25,8 @@
2525
from airflow.sensors.base import BaseSensorOperator
2626
from airflow.sensors.date_time import DateTimeSensorAsync
2727
from airflow.serialization.pydantic.dag_run import DagRunPydantic
28-
from airflow.triggers.temporal import TimeDeltaTrigger
28+
from airflow.triggers.temporal import DateTimeTrigger, TimeDeltaTrigger
29+
from airflow.utils import timezone
2930
from airflow.utils.context import Context
3031
from airflow.utils.state import DagRunState
3132

@@ -80,11 +81,18 @@ def __init__( # type:ignore
8081
else:
8182
self.target_time = target_time
8283

83-
def execute(self, context: Context) -> None:
84+
def execute(self, context: Context) -> NoReturn:
8485
if self.simulate:
8586
print("Nominally we would sleep, but this is a simulation. Returning now.")
86-
return
87-
super().execute(context=context)
87+
self.defer(
88+
method_name="execute_complete",
89+
trigger=DateTimeTrigger(
90+
moment=timezone.parse("1980-01-01"),
91+
end_from_trigger=self.end_from_trigger,
92+
),
93+
)
94+
else:
95+
super().execute(context=context)
8896

8997

9098
class WaitForRevisionToBeElected(ICRolloutSensorBaseOperator):

0 commit comments

Comments
 (0)