Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ 2 lib, 3 stdenv, 4 python, 5 buildPythonPackage, 6 fetchFromGitHub, 7 alembic, 8 argcomplete, 9 asgiref, 10 attrs, 11 blinker, 12 cached-property, 13 cattrs, 14 clickclick, 15 colorlog, 16 configupdater, 17 connexion, 18 cron-descriptor, 19 croniter, 20 cryptography, 21 deprecated, 22 dill, 23 flask, 24 flask-login, 25 flask-appbuilder, 26 flask-caching, 27 flask-session, 28 flask-wtf, 29 gitpython, 30 google-re2, 31 graphviz, 32 gunicorn, 33 httpx, 34 iso8601, 35 importlib-resources, 36 importlib-metadata, 37 inflection, 38 itsdangerous, 39 jinja2, 40 jsonschema, 41 lazy-object-proxy, 42 linkify-it-py, 43 lockfile, 44 markdown, 45 markupsafe, 46 marshmallow-oneofschema, 47 mdit-py-plugins, 48 numpy, 49 openapi-spec-validator, 50 opentelemetry-api, 51 opentelemetry-exporter-otlp, 52 pandas, 53 pathspec, 54 pendulum, 55 psutil, 56 pydantic, 57 pygments, 58 pyjwt, 59 python-daemon, 60 python-dateutil, 61 python-nvd3, 62 python-slugify, 63 python3-openid, 64 pythonOlder, 65 pyyaml, 66 rich, 67 rich-argparse, 68 setproctitle, 69 sqlalchemy, 70 sqlalchemy-jsonfield, 71 swagger-ui-bundle, 72 tabulate, 73 tenacity, 74 termcolor, 75 typing-extensions, 76 unicodecsv, 77 werkzeug, 78 freezegun, 79 pytest-asyncio, 80 pytestCheckHook, 81 time-machine, 82 mkYarnPackage, 83 fetchYarnDeps, 84 writeScript, 85 86 # Extra airflow providers to enable 87 enabledProviders ? [ ], 88}: 89let 90 version = "2.7.3"; 91 92 airflow-src = fetchFromGitHub { 93 owner = "apache"; 94 repo = "airflow"; 95 rev = "refs/tags/${version}"; 96 # Download using the git protocol rather than using tarballs, because the 97 # GitHub archive tarballs don't appear to include tests 98 forceFetchGit = true; 99 hash = "sha256-+YbiKFZLigSDbHPaUKIl97kpezW1rIt/j09MMa6lwhQ="; 100 }; 101 102 # airflow bundles a web interface, which is built using webpack by an undocumented shell script in airflow's source tree. 103 # This replicates this shell script, fixing bugs in yarn.lock and package.json 104 105 airflow-frontend = mkYarnPackage rec { 106 name = "airflow-frontend"; 107 108 src = "${airflow-src}/airflow/www"; 109 packageJSON = ./package.json; 110 111 offlineCache = fetchYarnDeps { 112 yarnLock = "${src}/yarn.lock"; 113 hash = "sha256-WQKuQgNp35fU6z7owequXOSwoUGJDJYcUgkjPDMOops="; 114 }; 115 116 distPhase = "true"; 117 118 # The webpack license plugin tries to create /licenses when given the 119 # original relative path 120 postPatch = '' 121 sed -i 's!../../../../licenses/LICENSES-ui.txt!licenses/LICENSES-ui.txt!' webpack.config.js 122 ''; 123 124 configurePhase = '' 125 cp -r $node_modules node_modules 126 ''; 127 128 buildPhase = '' 129 yarn --offline build 130 find package.json yarn.lock static/css static/js -type f | sort | xargs md5sum > static/dist/sum.md5 131 ''; 132 133 installPhase = '' 134 mkdir -p $out/static/ 135 cp -r static/dist $out/static 136 ''; 137 }; 138 139 # Import generated file with metadata for provider dependencies and imports. 140 # Enable additional providers using enabledProviders above. 141 providers = import ./providers.nix; 142 getProviderDeps = provider: map (dep: python.pkgs.${dep}) providers.${provider}.deps; 143 getProviderImports = provider: providers.${provider}.imports; 144 providerDependencies = lib.concatMap getProviderDeps enabledProviders; 145 providerImports = lib.concatMap getProviderImports enabledProviders; 146in 147buildPythonPackage rec { 148 pname = "apache-airflow"; 149 inherit version; 150 format = "setuptools"; 151 src = airflow-src; 152 153 disabled = pythonOlder "3.7"; 154 155 propagatedBuildInputs = [ 156 alembic 157 argcomplete 158 asgiref 159 attrs 160 blinker 161 cached-property 162 cattrs 163 clickclick 164 colorlog 165 configupdater 166 connexion 167 cron-descriptor 168 croniter 169 cryptography 170 deprecated 171 dill 172 flask 173 flask-appbuilder 174 flask-caching 175 flask-session 176 flask-wtf 177 flask-login 178 gitpython 179 google-re2 180 graphviz 181 gunicorn 182 httpx 183 iso8601 184 importlib-resources 185 inflection 186 itsdangerous 187 jinja2 188 jsonschema 189 lazy-object-proxy 190 linkify-it-py 191 lockfile 192 markdown 193 markupsafe 194 marshmallow-oneofschema 195 mdit-py-plugins 196 numpy 197 openapi-spec-validator 198 opentelemetry-api 199 opentelemetry-exporter-otlp 200 pandas 201 pathspec 202 pendulum 203 psutil 204 pydantic 205 pygments 206 pyjwt 207 python-daemon 208 python-dateutil 209 python-nvd3 210 python-slugify 211 python3-openid 212 pyyaml 213 rich 214 rich-argparse 215 setproctitle 216 sqlalchemy 217 sqlalchemy-jsonfield 218 swagger-ui-bundle 219 tabulate 220 tenacity 221 termcolor 222 typing-extensions 223 unicodecsv 224 werkzeug 225 ] 226 ++ lib.optionals (pythonOlder "3.9") [ 227 importlib-metadata 228 ] 229 ++ providerDependencies; 230 231 buildInputs = [ 232 airflow-frontend 233 ]; 234 235 nativeCheckInputs = [ 236 freezegun 237 pytest-asyncio 238 pytestCheckHook 239 time-machine 240 ]; 241 242 # By default, source code of providers is included but unusable due to missing 243 # transitive dependencies. To enable a provider, add it to extraProviders 244 # above 245 INSTALL_PROVIDERS_FROM_SOURCES = "true"; 246 247 postPatch = '' 248 # https://github.com/apache/airflow/issues/33854 249 substituteInPlace pyproject.toml \ 250 --replace '[project]' $'[project]\nname = "apache-airflow"\nversion = "${version}"' 251 '' 252 + lib.optionalString stdenv.hostPlatform.isDarwin '' 253 # Fix failing test on Hydra 254 substituteInPlace airflow/utils/db.py \ 255 --replace "/tmp/sqlite_default.db" "$TMPDIR/sqlite_default.db" 256 ''; 257 258 pythonRelaxDeps = [ 259 "colorlog" 260 "flask-appbuilder" 261 "opentelemetry-api" 262 "pathspec" 263 ]; 264 265 # allow for gunicorn processes to have access to Python packages 266 makeWrapperArgs = [ 267 "--prefix PYTHONPATH : $PYTHONPATH" 268 ]; 269 270 postInstall = '' 271 cp -rv ${airflow-frontend}/static/dist $out/${python.sitePackages}/airflow/www/static 272 # Needed for pythonImportsCheck below 273 export HOME=$(mktemp -d) 274 ''; 275 276 pythonImportsCheck = [ 277 "airflow" 278 ] 279 ++ providerImports; 280 281 preCheck = '' 282 export AIRFLOW_HOME=$HOME 283 export AIRFLOW__CORE__UNIT_TEST_MODE=True 284 export AIRFLOW_DB="$HOME/airflow.db" 285 export PATH=$PATH:$out/bin 286 287 airflow version 288 airflow db init 289 airflow db reset -y 290 ''; 291 292 enabledTestPaths = [ 293 "tests/core/test_core.py" 294 ]; 295 296 disabledTests = lib.optionals stdenv.hostPlatform.isDarwin [ 297 "bash_operator_kill" # psutil.AccessDenied 298 ]; 299 300 # Updates yarn.lock and package.json 301 passthru.updateScript = writeScript "update.sh" '' 302 #!/usr/bin/env nix-shell 303 #!nix-shell -i bash -p common-updater-scripts curl pcre "python3.withPackages (ps: with ps; [ pyyaml ])" yarn2nix 304 305 set -euo pipefail 306 307 # Get new version 308 new_version="$(curl -s https://airflow.apache.org/docs/apache-airflow/stable/release_notes.html | 309 pcregrep -o1 'Airflow ([0-9.]+).' | head -1)" 310 update-source-version ${pname} "$new_version" 311 312 # Update frontend 313 cd ./pkgs/servers/apache-airflow 314 curl -O https://raw.githubusercontent.com/apache/airflow/$new_version/airflow/www/yarn.lock 315 curl -O https://raw.githubusercontent.com/apache/airflow/$new_version/airflow/www/package.json 316 yarn2nix > yarn.nix 317 318 # update provider dependencies 319 ./update-providers.py 320 ''; 321 322 # Note on testing the web UI: 323 # You can (manually) test the web UI as follows: 324 # 325 # nix shell .#apache-airflow 326 # airflow db reset # WARNING: this will wipe any existing db state you might have! 327 # airflow db init 328 # airflow standalone 329 # 330 # Then navigate to the localhost URL using the credentials printed, try 331 # triggering the 'example_bash_operator' and 'example_bash_operator' DAGs and 332 # see if they report success. 333 334 meta = with lib; { 335 description = "Programmatically author, schedule and monitor data pipelines"; 336 homepage = "https://airflow.apache.org/"; 337 license = licenses.asl20; 338 maintainers = with maintainers; [ 339 bhipple 340 gbpdt 341 ingenieroariel 342 ]; 343 knownVulnerabilities = [ 344 "CVE-2023-50943" 345 "CVE-2023-50944" 346 ]; 347 }; 348}