2016-11-28 31 views
11

Tôi đang cố gắng thiết lập một dự án sử dụng các đường ống Jenkins mới sáng bóng, cụ thể hơn là một dự án đa ngành.Jenkinsfile và Python virtualenv

Tôi đã một Jenkinsfile tạo ra trong một chi nhánh kiểm tra như sau:

node { 
    stage 'Preparing VirtualEnv' 
    if (!fileExists('.env')){ 
     echo 'Creating virtualenv ...' 
     sh 'virtualenv --no-site-packages .env' 
    } 
    sh '. .env/bin/activate' 
    sh 'ls -all' 
    if (fileExists('requirements/preinstall.txt')){ 
     sh 'pip install -r requirements/preinstall.txt' 
    } 
    sh 'pip install -r requirements/test.txt' 
    stage 'Unittests' 
    sh './manage.py test --noinput' 
} 

Nó đáng chú ý preinstall.txt rằng sẽ cập nhật pip

Tôi nhận được lỗi như sau:

OSError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/pip' 

Có vẻ như nó đang cố gắng cập nhật pip trong env toàn cục thay vì bên trong virtualenv, và có vẻ như mỗi bước sh đều nằm trong ngữ cảnh riêng của nó, làm cách nào để chúng thực hiện lệnh wit hin cùng bối cảnh?

+0

'kích hoạt' chỉ áp dụng cho vỏ instace nó được chạy trong, trong trường hợp của bạn là một dòng. Hãy thử chạy 'pip' trong venvới đường dẫn đầy đủ và' manage.py' với (đường dẫn đầy đủ) 'python'. –

Trả lời

5

Điều bạn đang cố gắng thực hiện sẽ không hoạt động. Mỗi khi bạn gọi lệnh sh, jenkins sẽ tạo một trình bao mới.

Điều này có nghĩa là nếu bạn sử dụng .env/bin/activate trong một sh, nó sẽ chỉ là nguồn trong phiên trình bao đó. Kết quả là trong lệnh sh mới, bạn phải nguồn lại tệp (nếu bạn xem xét kỹ hơn đầu ra của bàn điều khiển, bạn sẽ thấy rằng Jenkins sẽ thực sự tạo các tệp vỏ tạm thời mỗi lần yu chạy dấu phẩy.

bạn có nên nguồn tập tin .env/bin/activate vào đầu mỗi lệnh shell (bạn có thể sử dụng qoutes triple cho chuỗi multiline), như vậy

if (fileExists('requirements/preinstall.txt')) { 
    sh """ 
    . .env/bin/activate 
    pip install -r requirements/preinstall.txt 
    """ 
} 
... 
sh """ 
. .env/bin/activate 
pip install -r requirements/test.txt 
""" 
} 
stage("Unittests") { 
    sh """ 
    . .env/bin/activate 
    ./manage.py test --noinput 
    """ 
} 

hoặc chạy nó tất cả trong một vỏ

sh """ 
. .env/bin/activate 
if [[ -f requirements/preinstall.txt ]]; then 
    pip install -r requirements/preinstall.txt 
fi 
pip install -r requirements/test.txt 
./manage.py test --noinput 
""" 
+4

Đáng buồn thay, cách giải quyết này làm cho việc duy trì đường ống dẫn đến cơn ác mộng, chúng tôi cần mở rộng đường ống DSL để kích hoạt trường hợp sử dụng này và để tránh kết thúc việc này. Cách giải quyết này hoạt động cho các đường ống đơn giản nhưng một khi bạn phát triển thành những đường phức tạp, việc kích hoạt sẽ trở thành cơn ác mộng. Hãy suy nghĩ về các trường hợp ngoại lệ và thậm chí là các khối chạy nếu việc tạo virtualenv thất bại. – sorin

+0

Thật không may tôi phải đồng ý @sorin. Nó tiếp tục nhận được tốt hơn, nhưng thường xuyên công cụ phá vỡ hoặc một workaround là cần thiết. Mặt khác, wee có thể cung cấp cho mọi người đóng góp một số chùng để dành thời gian cho nó. Về vấn đề này, bạn luôn có thể đặt một kịch bản trong repo của bạn với logic, và chỉ cần gọi – Rik

1

Lik e Rik được đăng, virtualenvs không hoạt động tốt trong môi trường đường dẫn Jenkins, vì một trình bao mới được tạo cho mỗi lệnh.

Tôi đã tạo một plugin khiến quá trình này hơi khó chịu hơn, có thể tìm thấy ở đây: https://wiki.jenkins.io/display/JENKINS/Pyenv+Pipeline+Plugin. Về cơ bản nó chỉ kết thúc tốt đẹp mỗi cuộc gọi theo cách kích hoạt virtualenv trước khi chạy lệnh. Điều này trong chính nó là khó khăn, như một số phương pháp chạy nhiều lệnh nội tuyến được chia thành hai lệnh riêng biệt bởi Jenkins, gây ảo hóa kích hoạt không còn áp dụng.

0

Tôi mới sử dụng các tệp Jenkins. Đây là cách tôi đã làm việc xung quanh vấn đề môi trường ảo. (Tôi đang chạy Python3, Jenkins 2.73.1)

Lưu ý: Chỉ cần rõ ràng, tôi không nói đây là cách tốt để giải quyết vấn đề, cũng như tôi đã thử nghiệm đủ để đứng sau cách tiếp cận này, nhưng ở đây những gì đang làm việc cho tôi hôm nay:

Tôi đã chơi xung quanh bằng cách bỏ qua venv 'kích hoạt' bằng cách gọi trực tiếp thông dịch viên trăn của môi trường ảo. Vì vậy, thay vì:

source ~/venv/bin/activate  

người ta có thể sử dụng:

~/venv/bin/python3 my_script.py 

tôi vượt qua đường dẫn đến ảo thông dịch viên python môi trường của tôi qua file rc của vỏ Về lý thuyết, mỗi vỏ (Trong trường hợp của tôi, ~/.bashrc.) Cuộc gọi Jenkins nên đọc tệp tài nguyên này. Trong thực tế, tôi phải khởi động lại Jenkins sau khi thực hiện thay đổi đối với tệp tài nguyên shell.

HOME_DIR=~ 
export VENV_PATH="$HOME_DIR/venvs/my_venv" 
export PYTHON_INTERPRETER="${VENV_PATH}/bin/python3" 

My Jenkinsfile trông tương tự như sau:

pipeline { 
    agent { 
     label 'my_slave' 
    } 

    stages { 
     stage('Stage1') { 
      steps { 
       // sh 'echo $PYTHON_INTERPRETER' 
       // sh 'env | sort' 
       sh "$PYTHON_INTERPRETER my_script.py " 
      } 
     } 
    } 
} 

Vì vậy, khi đường ống được chạy, sh có $ giá trị môi trường PYTHON_INTERPRETER thiết lập.

Lưu ý một thiếu sót của phương pháp này là bây giờ tệp Jenkins không chứa tất cả thông tin cần thiết để chạy tập lệnh đúng cách. Hy vọng rằng điều này sẽ giúp bạn thoát khỏi mặt đất.

Các vấn đề liên quan