skypilot-nightly 1.0.0.dev20250715__py3-none-any.whl → 1.0.0.dev20250717__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sky/__init__.py +4 -2
- sky/adaptors/nebius.py +6 -0
- sky/backends/backend.py +8 -4
- sky/backends/cloud_vm_ray_backend.py +50 -1
- sky/backends/docker_utils.py +1 -1
- sky/backends/local_docker_backend.py +2 -1
- sky/catalog/common.py +60 -50
- sky/catalog/data_fetchers/fetch_gcp.py +1 -0
- sky/catalog/data_fetchers/fetch_nebius.py +308 -0
- sky/catalog/gcp_catalog.py +24 -7
- sky/catalog/kubernetes_catalog.py +5 -1
- sky/client/cli/command.py +180 -77
- sky/client/cli/git.py +549 -0
- sky/client/common.py +1 -1
- sky/clouds/gcp.py +1 -1
- sky/clouds/hyperbolic.py +2 -0
- sky/clouds/nebius.py +6 -4
- sky/dashboard/out/404.html +1 -1
- sky/dashboard/out/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js +1 -0
- sky/dashboard/out/_next/static/chunks/1141-d8c6404a7c6fffe6.js +11 -0
- sky/dashboard/out/_next/static/chunks/1746.27d40aedc22bd2d6.js +60 -0
- sky/dashboard/out/_next/static/chunks/2641.35edc9ccaeaad9e3.js +1 -0
- sky/dashboard/out/_next/static/chunks/{3785.b3cc2bc1d49d2c3c.js → 3785.95b94f18aaec7233.js} +1 -1
- sky/dashboard/out/_next/static/chunks/4869.bdd42f14b51d1d6f.js +16 -0
- sky/dashboard/out/_next/static/chunks/6990-dcb411b566e64cde.js +1 -0
- sky/dashboard/out/_next/static/chunks/{9025.a7c44babfe56ce09.js → 9025.133e9ba5c780afeb.js} +1 -1
- sky/dashboard/out/_next/static/chunks/9847.46e613d000c55859.js +30 -0
- sky/dashboard/out/_next/static/chunks/pages/{_app-e0f63ea4704026ad.js → _app-771a40cde532309b.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-9096ea50b8e2cf9e.js +6 -0
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-14d404b7dd28502a.js +16 -0
- sky/dashboard/out/_next/static/chunks/pages/{users-cd43fb3c122eedde.js → users-19e98664bdd61643.js} +1 -1
- sky/dashboard/out/_next/static/chunks/pages/volumes-61ea7ba7e56f8d06.js +1 -0
- sky/dashboard/out/_next/static/chunks/pages/{workspaces-06bde99155fa6292.js → workspaces-a1e43d9ef51a9cea.js} +1 -1
- sky/dashboard/out/_next/static/chunks/{webpack-4a336bff3bcec29a.js → webpack-c3b45b7b0eaef66f.js} +1 -1
- sky/dashboard/out/_next/static/css/219887b94512388c.css +3 -0
- sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
- sky/dashboard/out/clusters/[cluster].html +1 -1
- sky/dashboard/out/clusters.html +1 -1
- sky/dashboard/out/config.html +1 -1
- sky/dashboard/out/index.html +1 -1
- sky/dashboard/out/infra/[context].html +1 -1
- sky/dashboard/out/infra.html +1 -1
- sky/dashboard/out/jobs/[job].html +1 -1
- sky/dashboard/out/jobs.html +1 -1
- sky/dashboard/out/users.html +1 -1
- sky/dashboard/out/volumes.html +1 -1
- sky/dashboard/out/workspace/new.html +1 -1
- sky/dashboard/out/workspaces/[name].html +1 -1
- sky/dashboard/out/workspaces.html +1 -1
- sky/exceptions.py +5 -0
- sky/execution.py +5 -1
- sky/provision/hyperbolic/__init__.py +1 -0
- sky/provision/hyperbolic/instance.py +10 -0
- sky/provision/kubernetes/utils.py +6 -0
- sky/server/common.py +4 -3
- sky/setup_files/MANIFEST.in +1 -0
- sky/setup_files/dependencies.py +3 -1
- sky/task.py +12 -2
- sky/utils/command_runner.py +144 -35
- sky/utils/controller_utils.py +4 -3
- sky/utils/git.py +9 -0
- sky/utils/git_clone.sh +460 -0
- sky/utils/schemas.py +15 -1
- sky/utils/tempstore.py +20 -1
- {skypilot_nightly-1.0.0.dev20250715.dist-info → skypilot_nightly-1.0.0.dev20250717.dist-info}/METADATA +5 -3
- {skypilot_nightly-1.0.0.dev20250715.dist-info → skypilot_nightly-1.0.0.dev20250717.dist-info}/RECORD +79 -75
- sky/dashboard/out/_next/static/chunks/1141-726e5a3f00b67185.js +0 -11
- sky/dashboard/out/_next/static/chunks/1691.44e378727a41f3b5.js +0 -21
- sky/dashboard/out/_next/static/chunks/3256.7257acd01b481bed.js +0 -11
- sky/dashboard/out/_next/static/chunks/4697.f5421144224da9fc.js +0 -20
- sky/dashboard/out/_next/static/chunks/6990-d0dc765474fa0eca.js +0 -1
- sky/dashboard/out/_next/static/chunks/8982.a2e214068f30a857.js +0 -1
- sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]/[job]-4608dc89f95eba89.js +0 -6
- sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-980d6f6b64ca7833.js +0 -16
- sky/dashboard/out/_next/static/chunks/pages/volumes-4ebf6484f7216387.js +0 -1
- sky/dashboard/out/_next/static/css/eacc7d65a8686c76.css +0 -3
- sky/dashboard/out/_next/static/y4pSeZ-9XymSDfPlcWhVO/_buildManifest.js +0 -1
- /sky/dashboard/out/_next/static/{y4pSeZ-9XymSDfPlcWhVO → Et5IQ5Y3WvH608nXClo4z}/_ssgManifest.js +0 -0
- /sky/dashboard/out/_next/static/chunks/{1043-5e5ef6198735ff7e.js → 1043-90a88c46f27b3df5.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{1871-4d1f786e83bd9ffe.js → 1871-76491ac174a95278.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{3698-52ad1ca228faa776.js → 3698-9fa11dafb5cad4a6.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{6601-d38d10f957dff832.js → 6601-d4a381403a8bae91.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{8969-13bb52ce3cffa4e3.js → 8969-743abf4bc86baf48.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{938-8e25c8ea0baa271a.js → 938-6a9ffdaa21eee969.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/{9470-21d059a1dfa03f61.js → 9470-b6f6a35283863a6f.js} +0 -0
- /sky/dashboard/out/_next/static/chunks/pages/clusters/{[cluster]-0fbfb1dd0b08c90c.js → [cluster]-0c37ee1ac5f3474d.js} +0 -0
- {skypilot_nightly-1.0.0.dev20250715.dist-info → skypilot_nightly-1.0.0.dev20250717.dist-info}/WHEEL +0 -0
- {skypilot_nightly-1.0.0.dev20250715.dist-info → skypilot_nightly-1.0.0.dev20250717.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250715.dist-info → skypilot_nightly-1.0.0.dev20250717.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250715.dist-info → skypilot_nightly-1.0.0.dev20250717.dist-info}/top_level.txt +0 -0
sky/dashboard/out/infra.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra-ae9d2f705ce582c9.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-162f3033ffcd3d31.js" defer=""></script><script src="/dashboard/_next/static/chunks/5230-df791914b54d91d9.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-5ea3ffa10fc884f2.js" defer=""></script><script src="/dashboard/_next/static/chunks/1664-d65361e92b85e786.js" defer=""></script><script src="/dashboard/_next/static/chunks/804-9f5e98ce84d46bdd.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-eab0e9c16b64fd9f.js" defer=""></script><script src="/dashboard/_next/static/chunks/3698-9fa11dafb5cad4a6.js" defer=""></script><script src="/dashboard/_next/static/chunks/9470-b6f6a35283863a6f.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-743abf4bc86baf48.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-14d404b7dd28502a.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/jobs.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs-5bbdc71878f0a068.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/users.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/users-19e98664bdd61643.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/users","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/dashboard/out/volumes.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/volumes-61ea7ba7e56f8d06.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/volumes","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspace/new-5629d4e551dba1ee.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspace/new","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-162f3033ffcd3d31.js" defer=""></script><script src="/dashboard/_next/static/chunks/5230-df791914b54d91d9.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-5ea3ffa10fc884f2.js" defer=""></script><script src="/dashboard/_next/static/chunks/1664-d65361e92b85e786.js" defer=""></script><script src="/dashboard/_next/static/chunks/804-9f5e98ce84d46bdd.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/3947-b059261d6fa88a1f.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-eab0e9c16b64fd9f.js" defer=""></script><script src="/dashboard/_next/static/chunks/3698-9fa11dafb5cad4a6.js" defer=""></script><script src="/dashboard/_next/static/chunks/9470-b6f6a35283863a6f.js" defer=""></script><script src="/dashboard/_next/static/chunks/6990-dcb411b566e64cde.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-743abf4bc86baf48.js" defer=""></script><script src="/dashboard/_next/static/chunks/1043-90a88c46f27b3df5.js" defer=""></script><script src="/dashboard/_next/static/chunks/6601-d4a381403a8bae91.js" defer=""></script><script src="/dashboard/_next/static/chunks/938-6a9ffdaa21eee969.js" defer=""></script><script src="/dashboard/_next/static/chunks/1141-d8c6404a7c6fffe6.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces/%5Bname%5D-7c0187f43757a548.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces/[name]","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
@@ -1 +1 @@
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/219887b94512388c.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/219887b94512388c.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-c3b45b7b0eaef66f.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-efc06c2733009cd3.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-c0a4f1ea606d48d2.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-771a40cde532309b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/workspaces-a1e43d9ef51a9cea.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/Et5IQ5Y3WvH608nXClo4z/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/workspaces","query":{},"buildId":"Et5IQ5Y3WvH608nXClo4z","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|
sky/exceptions.py
CHANGED
sky/execution.py
CHANGED
@@ -23,6 +23,7 @@ from sky.utils import dag_utils
|
|
23
23
|
from sky.utils import resources_utils
|
24
24
|
from sky.utils import rich_utils
|
25
25
|
from sky.utils import status_lib
|
26
|
+
from sky.utils import tempstore
|
26
27
|
from sky.utils import timeline
|
27
28
|
from sky.utils import ux_utils
|
28
29
|
|
@@ -430,7 +431,7 @@ def _execute_dag(
|
|
430
431
|
logger.info(ux_utils.starting_message('Syncing files.'))
|
431
432
|
|
432
433
|
if do_workdir:
|
433
|
-
backend.sync_workdir(handle, task.workdir)
|
434
|
+
backend.sync_workdir(handle, task.workdir, task.envs_and_secrets)
|
434
435
|
|
435
436
|
if do_file_mounts:
|
436
437
|
backend.sync_file_mounts(handle, task.file_mounts,
|
@@ -476,6 +477,9 @@ def _execute_dag(
|
|
476
477
|
|
477
478
|
@timeline.event
|
478
479
|
@usage_lib.entrypoint
|
480
|
+
# A launch routine will share tempfiles between steps, so we init a tempdir
|
481
|
+
# for the launch routine and gc the entire dir after launch.
|
482
|
+
@tempstore.with_tempdir
|
479
483
|
def launch(
|
480
484
|
task: Union['sky.Task', 'sky.Dag'],
|
481
485
|
cluster_name: Optional[str] = None,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Hyperbolic provisioner for SkyPilot."""
|
2
2
|
|
3
3
|
from sky.provision.hyperbolic.config import bootstrap_instances
|
4
|
+
from sky.provision.hyperbolic.instance import cleanup_custom_multi_network
|
4
5
|
from sky.provision.hyperbolic.instance import cleanup_ports
|
5
6
|
from sky.provision.hyperbolic.instance import get_cluster_info
|
6
7
|
from sky.provision.hyperbolic.instance import open_ports
|
@@ -414,6 +414,16 @@ def cleanup_ports(
|
|
414
414
|
raise NotImplementedError('cleanup_ports is not supported for Hyperbolic')
|
415
415
|
|
416
416
|
|
417
|
+
def cleanup_custom_multi_network(
|
418
|
+
cluster_name_on_cloud: str,
|
419
|
+
provider_config: Dict[str, Any],
|
420
|
+
failover: bool = False,
|
421
|
+
) -> None:
|
422
|
+
"""Cleanup custom multi-network. Not supported for Hyperbolic."""
|
423
|
+
raise NotImplementedError(
|
424
|
+
'cleanup_custom_multi_network is not supported for Hyperbolic')
|
425
|
+
|
426
|
+
|
417
427
|
def open_ports(
|
418
428
|
cluster_name_on_cloud: str,
|
419
429
|
ports: list,
|
@@ -554,6 +554,9 @@ class GKELabelFormatter(GPULabelFormatter):
|
|
554
554
|
return acc
|
555
555
|
elif is_tpu_on_gke(value):
|
556
556
|
return value
|
557
|
+
elif value == '':
|
558
|
+
# heterogenous cluster may have empty labels for cpu nodes.
|
559
|
+
return ''
|
557
560
|
else:
|
558
561
|
raise ValueError(
|
559
562
|
f'Invalid accelerator name in GKE cluster: {value}')
|
@@ -993,6 +996,9 @@ class GKEAutoscaler(Autoscaler):
|
|
993
996
|
node_accelerator_type = (
|
994
997
|
GKELabelFormatter.get_accelerator_from_label_value(
|
995
998
|
accelerator['acceleratorType']))
|
999
|
+
# handle heterogenous nodes.
|
1000
|
+
if not node_accelerator_type:
|
1001
|
+
continue
|
996
1002
|
node_accelerator_count = accelerator['acceleratorCount']
|
997
1003
|
if node_accelerator_type == requested_gpu_type and int(
|
998
1004
|
node_accelerator_count) >= requested_gpu_count:
|
sky/server/common.py
CHANGED
@@ -706,9 +706,10 @@ def process_mounts_in_task_on_api_server(task: str, env_vars: Dict[str, str],
|
|
706
706
|
continue
|
707
707
|
if 'workdir' in task_config:
|
708
708
|
workdir = task_config['workdir']
|
709
|
-
|
710
|
-
|
711
|
-
|
709
|
+
if isinstance(workdir, str):
|
710
|
+
task_config['workdir'] = str(
|
711
|
+
client_file_mounts_dir /
|
712
|
+
file_mounts_mapping[workdir].lstrip('/'))
|
712
713
|
if workdir_only:
|
713
714
|
continue
|
714
715
|
if 'file_mounts' in task_config:
|
sky/setup_files/MANIFEST.in
CHANGED
sky/setup_files/dependencies.py
CHANGED
@@ -66,6 +66,8 @@ install_requires = [
|
|
66
66
|
'prometheus_client>=0.8.0',
|
67
67
|
'passlib',
|
68
68
|
'pyjwt',
|
69
|
+
'gitpython',
|
70
|
+
'types-paramiko',
|
69
71
|
]
|
70
72
|
|
71
73
|
server_dependencies = [
|
@@ -174,7 +176,7 @@ extras_require: Dict[str, List[str]] = {
|
|
174
176
|
# 'vsphere-automation-sdk @ git+https://github.com/vmware/vsphere-automation-sdk-python.git@v8.0.1.0' pylint: disable=line-too-long
|
175
177
|
],
|
176
178
|
'nebius': [
|
177
|
-
'nebius>=0.2.
|
179
|
+
'nebius>=0.2.37',
|
178
180
|
] + aws_dependencies,
|
179
181
|
'hyperbolic': [], # No dependencies needed for hyperbolic
|
180
182
|
'server': server_dependencies,
|
sky/task.py
CHANGED
@@ -245,7 +245,7 @@ class Task:
|
|
245
245
|
run: Optional[CommandOrCommandGen] = None,
|
246
246
|
envs: Optional[Dict[str, str]] = None,
|
247
247
|
secrets: Optional[Dict[str, str]] = None,
|
248
|
-
workdir: Optional[str] = None,
|
248
|
+
workdir: Optional[Union[str, Dict[str, Any]]] = None,
|
249
249
|
num_nodes: Optional[int] = None,
|
250
250
|
volumes: Optional[Dict[str, str]] = None,
|
251
251
|
# Advanced:
|
@@ -301,10 +301,14 @@ class Task:
|
|
301
301
|
secrets: A dictionary of secret environment variables to set before
|
302
302
|
running the setup and run commands. These will be redacted in logs
|
303
303
|
and YAML output.
|
304
|
-
workdir: The local working directory
|
304
|
+
workdir: The local working directory or a git repository.
|
305
|
+
For a local working directory, this directory will be synced
|
305
306
|
to a location on the remote VM(s), and ``setup`` and ``run``
|
306
307
|
commands will be run under that location (thus, they can rely on
|
307
308
|
relative paths when invoking binaries).
|
309
|
+
If a git repository is provided, the repository will be cloned to
|
310
|
+
the working directory and the ``setup`` and ``run`` commands will
|
311
|
+
be run under the cloned repository.
|
308
312
|
num_nodes: The number of nodes to provision for this Task. If None,
|
309
313
|
treated as 1 node. If > 1, each node will execute its own
|
310
314
|
setup/run command, where ``run`` can either be a str, meaning all
|
@@ -498,6 +502,12 @@ class Task:
|
|
498
502
|
"""
|
499
503
|
if self.workdir is None:
|
500
504
|
return
|
505
|
+
# Only expand the workdir if it is a string
|
506
|
+
if isinstance(self.workdir, dict):
|
507
|
+
git_ref = self.workdir.get('ref')
|
508
|
+
if git_ref is not None:
|
509
|
+
self._metadata['git_commit'] = git_ref
|
510
|
+
return
|
501
511
|
user_workdir = self.workdir
|
502
512
|
self.workdir = os.path.abspath(os.path.expanduser(user_workdir))
|
503
513
|
if not os.path.isdir(self.workdir):
|
sky/utils/command_runner.py
CHANGED
@@ -6,14 +6,17 @@ import pathlib
|
|
6
6
|
import shlex
|
7
7
|
import sys
|
8
8
|
import time
|
9
|
-
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type,
|
9
|
+
from typing import (Any, Callable, Dict, Iterable, List, Optional, Tuple, Type,
|
10
|
+
Union)
|
10
11
|
|
12
|
+
from sky import exceptions
|
11
13
|
from sky import sky_logging
|
12
14
|
from sky.skylet import constants
|
13
15
|
from sky.skylet import log_lib
|
14
16
|
from sky.utils import common_utils
|
15
17
|
from sky.utils import context_utils
|
16
18
|
from sky.utils import control_master_utils
|
19
|
+
from sky.utils import git as git_utils
|
17
20
|
from sky.utils import subprocess_utils
|
18
21
|
from sky.utils import timeline
|
19
22
|
|
@@ -177,6 +180,20 @@ class CommandRunner:
|
|
177
180
|
def node_id(self) -> str:
|
178
181
|
return '-'.join(str(x) for x in self.node)
|
179
182
|
|
183
|
+
def _get_remote_home_dir(self) -> str:
|
184
|
+
# Use `echo ~` to get the remote home directory, instead of pwd or
|
185
|
+
# echo $HOME, because pwd can be `/` when the remote user is root
|
186
|
+
# and $HOME is not always set.
|
187
|
+
rc, remote_home_dir, stderr = self.run('echo ~',
|
188
|
+
require_outputs=True,
|
189
|
+
separate_stderr=True,
|
190
|
+
stream_logs=False)
|
191
|
+
if rc != 0:
|
192
|
+
raise ValueError('Failed to get remote home directory: '
|
193
|
+
f'{remote_home_dir + stderr}')
|
194
|
+
remote_home_dir = remote_home_dir.strip()
|
195
|
+
return remote_home_dir
|
196
|
+
|
180
197
|
def _get_command_to_run(
|
181
198
|
self,
|
182
199
|
cmd: Union[str, List[str]],
|
@@ -228,6 +245,27 @@ class CommandRunner:
|
|
228
245
|
command_str = ' '.join(command)
|
229
246
|
return command_str
|
230
247
|
|
248
|
+
def _get_remote_home_dir_with_retry(
|
249
|
+
self,
|
250
|
+
max_retry: int,
|
251
|
+
get_remote_home_dir: Callable[[], str],
|
252
|
+
) -> str:
|
253
|
+
"""Returns the remote home directory with retry."""
|
254
|
+
backoff = common_utils.Backoff(initial_backoff=1, max_backoff_factor=5)
|
255
|
+
retries_left = max_retry
|
256
|
+
assert retries_left > 0, f'max_retry {max_retry} must be positive.'
|
257
|
+
while retries_left >= 0:
|
258
|
+
try:
|
259
|
+
return get_remote_home_dir()
|
260
|
+
except Exception: # pylint: disable=broad-except
|
261
|
+
if retries_left == 0:
|
262
|
+
raise
|
263
|
+
sleep_time = backoff.current_backoff()
|
264
|
+
logger.warning(f'Failed to get remote home dir '
|
265
|
+
f'- retrying in {sleep_time} seconds.')
|
266
|
+
retries_left -= 1
|
267
|
+
time.sleep(sleep_time)
|
268
|
+
|
231
269
|
def _rsync(
|
232
270
|
self,
|
233
271
|
source: str,
|
@@ -248,23 +286,6 @@ class CommandRunner:
|
|
248
286
|
rsync_command.append(prefix_command)
|
249
287
|
rsync_command += ['rsync', RSYNC_DISPLAY_OPTION]
|
250
288
|
|
251
|
-
def _get_remote_home_dir_with_retry():
|
252
|
-
backoff = common_utils.Backoff(initial_backoff=1,
|
253
|
-
max_backoff_factor=5)
|
254
|
-
retries_left = max_retry
|
255
|
-
assert retries_left > 0, f'max_retry {max_retry} must be positive.'
|
256
|
-
while retries_left >= 0:
|
257
|
-
try:
|
258
|
-
return get_remote_home_dir()
|
259
|
-
except Exception: # pylint: disable=broad-except
|
260
|
-
if retries_left == 0:
|
261
|
-
raise
|
262
|
-
sleep_time = backoff.current_backoff()
|
263
|
-
logger.warning(f'Failed to get remote home dir '
|
264
|
-
f'- retrying in {sleep_time} seconds.')
|
265
|
-
retries_left -= 1
|
266
|
-
time.sleep(sleep_time)
|
267
|
-
|
268
289
|
# --filter
|
269
290
|
# The source is a local path, so we need to resolve it.
|
270
291
|
resolved_source = pathlib.Path(source).expanduser().resolve()
|
@@ -297,7 +318,9 @@ class CommandRunner:
|
|
297
318
|
pathlib.Path(target).expanduser().resolve())
|
298
319
|
else:
|
299
320
|
if target.startswith('~'):
|
300
|
-
remote_home_dir = _get_remote_home_dir_with_retry(
|
321
|
+
remote_home_dir = self._get_remote_home_dir_with_retry(
|
322
|
+
max_retry=max_retry,
|
323
|
+
get_remote_home_dir=get_remote_home_dir)
|
301
324
|
resolved_target = target.replace('~', remote_home_dir)
|
302
325
|
full_source_str = str(resolved_source)
|
303
326
|
if resolved_source.is_dir():
|
@@ -316,7 +339,9 @@ class CommandRunner:
|
|
316
339
|
else:
|
317
340
|
resolved_target = os.path.expanduser(target)
|
318
341
|
if source.startswith('~'):
|
319
|
-
remote_home_dir = _get_remote_home_dir_with_retry(
|
342
|
+
remote_home_dir = self._get_remote_home_dir_with_retry(
|
343
|
+
max_retry=max_retry,
|
344
|
+
get_remote_home_dir=get_remote_home_dir)
|
320
345
|
resolved_source = source.replace('~', remote_home_dir)
|
321
346
|
rsync_command.extend([
|
322
347
|
f'{maybe_dest_prefix}{resolved_source!r}',
|
@@ -451,6 +476,104 @@ class CommandRunner:
|
|
451
476
|
"""
|
452
477
|
raise NotImplementedError
|
453
478
|
|
479
|
+
@timeline.event
|
480
|
+
def git_clone(
|
481
|
+
self,
|
482
|
+
target_dir: str,
|
483
|
+
*,
|
484
|
+
# Advanced options.
|
485
|
+
log_path: str = os.devnull,
|
486
|
+
stream_logs: bool = True,
|
487
|
+
connect_timeout: Optional[int] = None,
|
488
|
+
max_retry: int = 1,
|
489
|
+
envs_and_secrets: Optional[Dict[str, str]] = None,
|
490
|
+
) -> None:
|
491
|
+
"""Clones a Git repository on the remote machine using git_clone.sh.
|
492
|
+
|
493
|
+
Note: Git environment variables (GIT_URL, GIT_BRANCH, GIT_TOKEN, etc.)
|
494
|
+
must be set before calling this function.
|
495
|
+
|
496
|
+
Args:
|
497
|
+
target_dir: Target directory where the repository will be cloned.
|
498
|
+
log_path: Redirect stdout/stderr to the log_path.
|
499
|
+
stream_logs: Stream logs to the stdout/stderr.
|
500
|
+
connect_timeout: timeout in seconds for the connection.
|
501
|
+
max_retry: The maximum number of retries for the rsync command.
|
502
|
+
This value should be non-negative.
|
503
|
+
envs_and_secrets: Environment variables and secrets to be set
|
504
|
+
before running the script.
|
505
|
+
Raises:
|
506
|
+
exceptions.CommandError: git clone command failed.
|
507
|
+
"""
|
508
|
+
# Find the git_clone.sh script path
|
509
|
+
git_clone_script_path = os.path.join(
|
510
|
+
os.path.dirname(os.path.abspath(__file__)), 'git_clone.sh')
|
511
|
+
|
512
|
+
if not os.path.exists(git_clone_script_path):
|
513
|
+
error_msg = f'git_clone.sh {git_clone_script_path} not found'
|
514
|
+
logger.error(error_msg)
|
515
|
+
raise exceptions.CommandError(1, '', error_msg, None)
|
516
|
+
|
517
|
+
# Remote script path (use a unique name to avoid conflicts)
|
518
|
+
script_hash = hashlib.md5(
|
519
|
+
f'{self.node_id}_{target_dir}'.encode()).hexdigest()[:8]
|
520
|
+
remote_script_path = f'/tmp/sky_git_clone_{script_hash}.sh'
|
521
|
+
|
522
|
+
# Step 1: Transfer the script to remote machine using rsync
|
523
|
+
logger.debug(
|
524
|
+
f'Transferring git_clone.sh to {self.node_id}:{remote_script_path}')
|
525
|
+
self.rsync(
|
526
|
+
source=git_clone_script_path,
|
527
|
+
target=remote_script_path,
|
528
|
+
up=True,
|
529
|
+
log_path=log_path,
|
530
|
+
stream_logs=False # Don't spam logs for script transfer
|
531
|
+
)
|
532
|
+
|
533
|
+
# Step 2: Execute the script on remote machine
|
534
|
+
if target_dir.startswith('~'):
|
535
|
+
remote_home_dir = self._get_remote_home_dir_with_retry(
|
536
|
+
max_retry=max_retry,
|
537
|
+
get_remote_home_dir=self._get_remote_home_dir)
|
538
|
+
target_dir = target_dir.replace('~', remote_home_dir)
|
539
|
+
quoted_target_dir = shlex.quote(target_dir)
|
540
|
+
quoted_script_path = shlex.quote(remote_script_path)
|
541
|
+
cmd = ''
|
542
|
+
log_cmd = ''
|
543
|
+
if envs_and_secrets:
|
544
|
+
for key, value in envs_and_secrets.items():
|
545
|
+
value = shlex.quote(value)
|
546
|
+
cmd += f'export {key}={value} && '
|
547
|
+
if (key == git_utils.GIT_TOKEN_ENV_VAR or
|
548
|
+
key == git_utils.GIT_SSH_KEY_ENV_VAR):
|
549
|
+
log_cmd += f'export {key}=******** && '
|
550
|
+
else:
|
551
|
+
log_cmd += f'export {key}={value} && '
|
552
|
+
exec_cmd = (f'bash {quoted_script_path} {quoted_target_dir} '
|
553
|
+
f'&& rm -f {quoted_script_path}')
|
554
|
+
cmd += exec_cmd
|
555
|
+
log_cmd += exec_cmd
|
556
|
+
|
557
|
+
logger.debug(f'Running git clone script on {self.node_id}: {log_cmd}')
|
558
|
+
|
559
|
+
backoff = common_utils.Backoff(initial_backoff=5, max_backoff_factor=5)
|
560
|
+
assert max_retry > 0, f'max_retry {max_retry} must be positive.'
|
561
|
+
while max_retry >= 0:
|
562
|
+
returncode = self.run(cmd,
|
563
|
+
log_path=log_path,
|
564
|
+
stream_logs=stream_logs,
|
565
|
+
connect_timeout=connect_timeout,
|
566
|
+
require_outputs=False)
|
567
|
+
if returncode == 0:
|
568
|
+
break
|
569
|
+
max_retry -= 1
|
570
|
+
time.sleep(backoff.current_backoff())
|
571
|
+
|
572
|
+
if returncode != 0:
|
573
|
+
error_msg = f'Git clone failed on {self.node_id}: {target_dir}'
|
574
|
+
logger.error(error_msg)
|
575
|
+
raise exceptions.CommandError(returncode, log_cmd, error_msg, None)
|
576
|
+
|
454
577
|
|
455
578
|
class SSHCommandRunner(CommandRunner):
|
456
579
|
"""Runner for SSH commands."""
|
@@ -941,20 +1064,6 @@ class KubernetesCommandRunner(CommandRunner):
|
|
941
1064
|
exceptions.CommandError: rsync command failed.
|
942
1065
|
"""
|
943
1066
|
|
944
|
-
def get_remote_home_dir() -> str:
|
945
|
-
# Use `echo ~` to get the remote home directory, instead of pwd or
|
946
|
-
# echo $HOME, because pwd can be `/` when the remote user is root
|
947
|
-
# and $HOME is not always set.
|
948
|
-
rc, remote_home_dir, stderr = self.run('echo ~',
|
949
|
-
require_outputs=True,
|
950
|
-
separate_stderr=True,
|
951
|
-
stream_logs=False)
|
952
|
-
if rc != 0:
|
953
|
-
raise ValueError('Failed to get remote home directory: '
|
954
|
-
f'{remote_home_dir + stderr}')
|
955
|
-
remote_home_dir = remote_home_dir.strip()
|
956
|
-
return remote_home_dir
|
957
|
-
|
958
1067
|
# Build command.
|
959
1068
|
helper_path = shlex.quote(
|
960
1069
|
os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
@@ -980,7 +1089,7 @@ class KubernetesCommandRunner(CommandRunner):
|
|
980
1089
|
# rsync with `kubectl` as the rsh command will cause ~/xx parsed as
|
981
1090
|
# /~/xx, so we need to replace ~ with the remote home directory. We
|
982
1091
|
# only need to do this when ~ is at the beginning of the path.
|
983
|
-
get_remote_home_dir=
|
1092
|
+
get_remote_home_dir=self._get_remote_home_dir)
|
984
1093
|
|
985
1094
|
|
986
1095
|
class LocalProcessCommandRunner(CommandRunner):
|
sky/utils/controller_utils.py
CHANGED
@@ -812,7 +812,7 @@ def translate_local_file_mounts_to_two_hop(
|
|
812
812
|
file_mount_id = 0
|
813
813
|
|
814
814
|
file_mounts_to_translate = task.file_mounts or {}
|
815
|
-
if task.workdir is not None:
|
815
|
+
if task.workdir is not None and isinstance(task.workdir, str):
|
816
816
|
file_mounts_to_translate[constants.SKY_REMOTE_WORKDIR] = task.workdir
|
817
817
|
task.workdir = None
|
818
818
|
|
@@ -880,7 +880,8 @@ def maybe_translate_local_file_mounts_and_sync_up(task: 'task_lib.Task',
|
|
880
880
|
copy_mounts = {}
|
881
881
|
|
882
882
|
has_local_source_paths_file_mounts = bool(copy_mounts)
|
883
|
-
has_local_source_paths_workdir = task.workdir is not None
|
883
|
+
has_local_source_paths_workdir = (task.workdir is not None and
|
884
|
+
isinstance(task.workdir, str))
|
884
885
|
|
885
886
|
msg = None
|
886
887
|
if has_local_source_paths_workdir and has_local_source_paths_file_mounts:
|
@@ -928,7 +929,7 @@ def maybe_translate_local_file_mounts_and_sync_up(task: 'task_lib.Task',
|
|
928
929
|
|
929
930
|
# Step 1: Translate the workdir to SkyPilot storage.
|
930
931
|
new_storage_mounts = {}
|
931
|
-
if task.workdir is not None:
|
932
|
+
if task.workdir is not None and isinstance(task.workdir, str):
|
932
933
|
workdir = task.workdir
|
933
934
|
task.workdir = None
|
934
935
|
if (constants.SKY_REMOTE_WORKDIR in original_file_mounts or
|
sky/utils/git.py
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
"""Git related constants."""
|
2
|
+
|
3
|
+
GIT_TOKEN_ENV_VAR = 'GIT_TOKEN'
|
4
|
+
GIT_SSH_KEY_PATH_ENV_VAR = 'GIT_SSH_KEY_PATH'
|
5
|
+
GIT_SSH_KEY_ENV_VAR = 'GIT_SSH_KEY'
|
6
|
+
GIT_URL_ENV_VAR = 'GIT_URL'
|
7
|
+
GIT_COMMIT_HASH_ENV_VAR = 'GIT_COMMIT_HASH'
|
8
|
+
GIT_BRANCH_ENV_VAR = 'GIT_BRANCH'
|
9
|
+
GIT_TAG_ENV_VAR = 'GIT_TAG'
|