536 lines
22 KiB
Plaintext
536 lines
22 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
|
|
"<div class=\"alert alert-block alert-info\">\n",
|
|
"<h1> Inżynieria uczenia maszynowego </h1>\n",
|
|
"<h2> 3. <i>System ciągłej integracji na przykładzie Jenkins</i> [laboratoria]</h2> \n",
|
|
"<h3> Tomasz Ziętkiewicz (2021)</h3>\n",
|
|
"</div>\n",
|
|
"\n",
|
|
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Ciągła integracja \n",
|
|
" - Jest to praktyka rozwoju projektów informatycznych polegająca na bardzo częstym włączaniu nowych zmian do głównej gałęzi (branch)\n",
|
|
" - Dzięki jej stosowaniu nie dochodzi do konfliktów przy łączeniu (mergowaniu) gałęzi rozwojowej (feature branch) z główną (master)\n",
|
|
" - Żeby stosować tę technikę, zmiany muszą być za każdym razem przetestowane, we wspólnym środowisku, tak, żeby działały u innych deweloperów\n",
|
|
" - Stąd narodziła się potrzeba stosowania systemów automatycznej ciągłej integracji\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Systemy ciągłej integracji \n",
|
|
"- Umożliwiają utomatyczne :\n",
|
|
" - budowanie\n",
|
|
" - testowanie \n",
|
|
" - wydawanie \n",
|
|
"oprogramowania, oraz automatyczne (lub ręczne) wykonywanie dowolnych \"zadań\"\n",
|
|
"- Zapewniają:\n",
|
|
" - wspólne środowisko do testowania zmian, replikowania błędów\n",
|
|
" - łatwość monitorowania zmian zachodzących w oprogramowaniu\n",
|
|
" - środowisko do integracji ze sobą części składowych (np. modułów, modeli) w jedną całość\n",
|
|
" - środowisko, w którym można stworzyć prosty graficzny interfejs służący do uruchamiania zadań z poziomu przeglądarki\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Systemy ciągłej integracji\n",
|
|
" - Jenkins <br/><img style=\"height: 50px;\" src=\"img/ci/jenkins.png\"/>\n",
|
|
" - Bamboo <br/><img style=\"height: 50px;\" src=\"img/ci/bamboo.png\"/>\n",
|
|
" - Circle CI <br/><img style=\"height: 50px;\" src=\"img/ci/circleci.png\"/>\n",
|
|
" - Team City <br/><img style=\"height: 50px;\" src=\"img/ci/teamcity.png\"/>\n",
|
|
" - Gitlab CI <br/><img style=\"height: 50px;\" src=\"img/ci/gitlabci.png\"/>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Jenkins \n",
|
|
"<br/><img style=\"height: 50px;\" src=\"img/ci/jenkins.png\"/>\n",
|
|
"- https://www.jenkins.io/\n",
|
|
"- System ciągłej integracji napisany w języku Java\n",
|
|
"- Pierwszy release: 2011\n",
|
|
"- Licencja Open Source (MIT)\n",
|
|
"- Dużo pluginów\n",
|
|
"- Aktywny rozwój, wspierany przez The Continuous Delivery Foundation i firmę Cloud Bees \n",
|
|
"- Działa jako aplikacja webowa z graficznym interfejsem\n",
|
|
"- Posiada też REST i CLI API"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Terminologia\n",
|
|
" - **Job, aka. Pipleine (Projekt)** - podstawowa jednostka organizacji pracy wykonywanej przez Jenkinsa. \n",
|
|
" - Posiada swoją konfigurację, która określa jakie polecenia będą wykonywane w jego ramach. \n",
|
|
" - Jeden pipeline może być wykonany wiele razy, za każdym razem tworząc nowe *Zadanie* (*Build*). \n",
|
|
" Przykładowy pipeline: https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world/\n",
|
|
"<img src=\"IUM_03/pipeline.jpg\"/>\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
" - **Build (Zadanie)** - instancja uruchomionego projektu. Może być w trakcie wykonywania, albo zakończona z jednym z rezultatów:\n",
|
|
" - Successful <img style=\"height: 30px;\" src=\"IUM_03/blue.png\"/>\n",
|
|
" - Unstable <img style=\"height: 30px;\" src=\"IUM_03/yellow.png\"/>\n",
|
|
" - Aborted <img style=\"height: 30px;\" src=\"IUM_03/aborted.png\"/>\n",
|
|
" - Failed <img style=\"height: 30px;\" src=\"IUM_03/red.png\"/>\n",
|
|
" Np: https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world/2/\n",
|
|
" - Śledzenie wyników działania buildu jak i debugowanie ewentualnych problemów ułatwiają:\n",
|
|
" - Wyjście z konsoli [(Console Output)](https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world/10/console) - tutaj widać logi wypisywane zarówno przez polecenia/funkcje Jenkinsowe jak i standardowe wyjście / wyjście błędów wykonywanych poleceń systemowych\n",
|
|
" - Workspace - to katalog roboczy, w którym uruchamiane są polecenia. Tutaj zostaje sklonowane repozytorium (jeśli je klonujemy), tu wywoływane będę polecenia systemowe. Można je przeglądać z poziomu przeglądarki, np. [tutaj](https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world-scripted/1/execution/node/3/ws/)\n",
|
|
" - Każdy uruchomiony build można zatrzymać (abort) co powoduje zaprzestanie jego wykonywania\n",
|
|
" - Build zakończony można usunąć (np. jeśli przez przypadek wypisaliśmy na konsolę nasze hasło)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Terminologia c.d.\n",
|
|
" - **Step (Krok?)** - każdy pipeline to sekwencja kroków do wykonania. \n",
|
|
" - W przypadku projektów typu Pipeline, kroki definiuje się w pliku \"Jenkinsfile\"\n",
|
|
" - Przykładowe kroki:\n",
|
|
" - wykonanie polecenia w konsoli (sh)\n",
|
|
" - sklonowanie repozytorium git (checkout)\n",
|
|
" - archiwizacja artefaktów (archiveArtifacts)\n",
|
|
" - kopiowanie artefaktów z innego zadania (copyArtifacts)\n",
|
|
" - uruchomienie innego zadania (build)\n",
|
|
" - **Stage (Etap?)** - Pozwala grupować kroki (steps). Na głównej stronie każdego pipeline możemy zobaczyć wizualizację poszczególnych etapów wraz z czasami ich wykonywania\n",
|
|
" - **Artifact (artefakt)** - plik zapisany przez zadanie do późniejszego wykorzytania (przez inne zadania, albo przez użytkownika). Jeśli jednym z kroków zdefiniowanych w projekcie będzie archiwizacja artefaktów, to każde pomyślnie zakończone zadanie będzie miało zapisane swoje artefakty\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Dokumentacja\n",
|
|
"- https://www.jenkins.io/doc/book/pipeline/\n",
|
|
"- \"Pipeline syntax\" na stronie każdego projektu, np: https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world/pipeline-syntax/\n",
|
|
"- Znaki zapytania <img style=\"height: 16px;\" src=\"IUM_03/help.png\"/> (W konfiguracji joba oraz w \"Pipeline Syntax\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Zadania [15 pkt]\n",
|
|
"Na dzisiejszych zajęciach przygotujemy dwa połączone ze sobą zadania:\n",
|
|
"1. Zadanie \"s123456-create-dataset\":\n",
|
|
" - pobiera i wybrany na poprzednich zajęciach zbiór danych\n",
|
|
" - dokonuje \"data preprocessing\"\n",
|
|
" - zapisuje wynik jako artefakt\n",
|
|
"2. Zadanie \"s123456-dataset-stats\":\n",
|
|
" - obliczy statystyki dla tego zbioru\n",
|
|
" - zapisze je jako artefakty"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Polecenia"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 1. Zaloguj się\n",
|
|
" - zaloguj się na https://tzietkiewicz.vm.wmi.amu.edu.pl:8080 za pomocą konta wydziałowego (jak w laboratoriach WMI)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 2. Utwórz nowy projekt (Job) [1pkt]\n",
|
|
"\n",
|
|
" - Istnieje kilka rodzajów projektów w Jenkinsie.\n",
|
|
"\n",
|
|
" - Po kliknięciu \"Nowy projekt\" zobaczymy listę dostępnych rodzajów projektów. Nas interesuje projekt typu \"Pipeline\".\n",
|
|
"\n",
|
|
" - Jako nazwę wpisz \"s123456-create-dataset\" (w miejsce 123456 proszę wstawić swój numer indeksu)\n",
|
|
" "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 3. Definicja Pipeline [2pkt]\n",
|
|
"\n",
|
|
" - Projekty typu Pipeline definiuje się w pliku Jenkinsfile za pomocą skryptu napisanego w jednym z dwóch dostępnych DSL (Domain Specific Language):\n",
|
|
" - [Scripted pipeline](https://www.jenkins.io/doc/book/pipeline/syntax/#scripted-pipeline) (podzbiór języka Groovy)\n",
|
|
" - [Declarative pipeline](https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-pipeline)\n",
|
|
"\n",
|
|
" - Pierwszy z nich daje większe możliwości, drugi jest łatwiejszy, lepiej udokumentowany, ale ma mniejszą siłę ekpresji.\n",
|
|
"\n",
|
|
" - Fragmenty kodu można również generować przy pomocy kreatora, dostępnego pod linkiem [Pipeline syntax](https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world/pipeline-syntax/) na stronie każdego projektu. Jest to bardzo przydatna funkcjonalność, nie tylko dla początkujących użytkowników\n",
|
|
"\n",
|
|
" - Jenkinsfile może być wprowadzony bezpośrednio z poziomu przeglądarki, albo pobrany z repozytorium.\n",
|
|
"\n",
|
|
" - Zacznijmy od pierwszej opcji. Jako przykładowego pipeline użyj przykładu Hello World podanego na https://jenkins.io/doc/book/pipeline/getting-started/\n",
|
|
"\n",
|
|
" - Zapisz projekt i spróbuj go uruchomić (przycisk \"Uruchom\"/\"Run\" na głównej stronie projektu).\n",
|
|
" "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"Przykładowy declarative Pipeline (https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world/):\n",
|
|
"\n",
|
|
"```groovy\n",
|
|
"pipeline {\n",
|
|
" agent any\n",
|
|
" //Definijuemy parametry, które będzie można podać podczas wywoływania zadania\n",
|
|
" parameters {\n",
|
|
" string (\n",
|
|
" defaultValue: 'Hello World!',\n",
|
|
" description: 'Tekst, którym chcesz przywitać świat',\n",
|
|
" name: 'INPUT_TEXT',\n",
|
|
" trim: false\n",
|
|
" )\n",
|
|
" }\n",
|
|
" stages {\n",
|
|
" stage('Hello') {\n",
|
|
" steps {\n",
|
|
" //Wypisz wartość parametru w konsoli (To nie jest polecenie bash, tylko groovy!)\n",
|
|
" echo \"INPUT_TEXT: ${INPUT_TEXT}\"\n",
|
|
" //Wywołaj w konsoli komendę \"figlet\", która generuje ASCI-art\n",
|
|
" sh \"figlet \\\"${INPUT_TEXT}\\\" | tee output.txt\"\n",
|
|
" }\n",
|
|
" }\n",
|
|
" stage('Goodbye!') {\n",
|
|
" steps {\n",
|
|
" echo 'Goodbye!'\n",
|
|
" //Zarchiwizuj wynik\n",
|
|
" archiveArtifacts 'output.txt'\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"Przykładowy scripted Pipeline (https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world-scripted/):\n",
|
|
"\n",
|
|
"```groovy\n",
|
|
"node {\n",
|
|
" stage('Preparation') {\n",
|
|
" properties([\n",
|
|
" parameters([\n",
|
|
" string(\n",
|
|
" defaultValue: 'Hello World!',\n",
|
|
" description: 'Tekst do wyświetlenie',\n",
|
|
" name: 'INPUT_TEXT',\n",
|
|
" trim: false\n",
|
|
" )\n",
|
|
" ])\n",
|
|
" ])\n",
|
|
" }\n",
|
|
" stage('Hello') {\n",
|
|
" //Wypisz wartość parametru w konsoli (To nie jest polecenie bash, tylko groovy!)\n",
|
|
" echo \"INPUT_TEXT: ${INPUT_TEXT}\"\n",
|
|
" //Wywołaj w konsoli komendę \"figlet\", która generuje ASCI-art\n",
|
|
" sh \"figlet \\\"${INPUT_TEXT}\\\" | tee output.txt\"\n",
|
|
" }\n",
|
|
" stage('Goodbye') {\n",
|
|
" echo 'Goodbye!'\n",
|
|
" //Zarchiwizuj wynik\n",
|
|
" archiveArtifacts 'output.txt'\n",
|
|
" }\n",
|
|
"}\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 4. Repozytorium [2 pkt]\n",
|
|
"\n",
|
|
"* Jeśli jeszcze tego nie zrobiłaś/zrobiłeś, stwórz nowe _publiczne_ repozytorium *ium_s123456* na wydziałowym serwerze \n",
|
|
" (https://laboratoria.wmi.amu.edu.pl/uslugi/pozostale-uslugi/git/)\n",
|
|
" W przypadku problemów z utworzeniem repozytorium zdalnie, może być to również dodwolne inne, publicznie dostępne repozytorium, np. na [GitHub](https://github.com/).\n",
|
|
" \n",
|
|
"* Sklonuj repozytorium lokalnie zgodnie ze wskazówkami wyświetlonymi po jego utworzeniu.\n",
|
|
" \n",
|
|
"* Utwórz plik \"Jenkinsfile\" (zawartość taka sama jak w punkcie 3.) i dodaj go do repozytorium.\n",
|
|
" \n",
|
|
"* W ustawieniach (konfiguracji) projektu przełącz \"Pipeline definition\" na \"Pipeline script from SCM\" i podaj ścieżkę do nowo utworzonego repozytorim.\n",
|
|
" \n",
|
|
"* Projekt powinien się uruchamiać za każdym razem, kiedy pojawią się nowe zmiany w repozytorium:\n",
|
|
" \"Konfiguracja\" -> \"Build Triggers\" -> \"Poll SCM\"\n",
|
|
"\n",
|
|
"* W razie problemów z klonowaniem/pushowaniem repozytorium, użyj protokołu ssh zamiast https (przy kopiowaniu ścieżki do repozytorium). Będzie to wymagało skopiowania zawartości pliku ~/.ssh/id_rsa.pub i wklejenia go w ustawieniach wydziałowego gita w zakładce SSH Keys"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 5. Zapisanie zbioru danych [4 pkt]\n",
|
|
"Edytuj zawartość Jenkinsfile tak, żeby realizował on następujące zadania:\n",
|
|
" 1. Sklonowanie repozytorium git (krok \"checkout: Check out from version control\")\n",
|
|
" 2. Wywołanie skryptu shella (krok \"sh: Shell Script\"). \n",
|
|
" - Skrypt powinien pobrać zbiór danych i zapisać wyniki jako artefakty\n",
|
|
" - Proszę też zasymulować przetwarzanie pliku, np. podział na podzbiory (shuf + head/tail), przycięcie do określonej długości (head/tail) lub usunięcie niektórych kolumn (cut).\n",
|
|
" - Domyślnie tutaj będzie skrypt, który napisali Państwo jako zadanie 1., ale ze względu na brakujące zależności, zapewne nie będzie on działać (rozwiążemy to na następnych zajęciach, korzystając z Dockera). Dlatego proszę w tym celu stworzyć prosty skrypt bash (*.sh).\n",
|
|
" - Skrypt powinien być zapisany w repozytorium. Unikamy wpisywania treści skryptów bezpośrednio w Jenkinsfile!\n",
|
|
" - Skrypt powinien zapisywać wyniki swojego działania do pliku\n",
|
|
" 3. Plik powstały w kroku 2. należy zarchiwizować (krok \"archiveArtifacts\"), tak, żeby mógł być wykorzystany przez kolejne projekty.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 6. Hasło do Kaggle\n",
|
|
" - Jeśli pobierasz swój zbiór z Kaggle, to możesz mieć problem z uwierzytelnieniem.\n",
|
|
" - Żeby kaggle CLI mogło połączyć się z Kaggle API, musi mieć podaną nazwę użytkownika i token.\n",
|
|
" - Kiedy używamy CLI lokalnie, korzysta ono z ściągniętego przez nas wcześniej pliku ~/.kaggle/kaggle.json, zawierającego nazwę użytkownika i hasło\n",
|
|
" - Zadania na Jenkinsie są wywoływane w systemie przez specjalnego użytkownika (jenkins). Użytkownik ten nie ma w swoim katalogu domowym pliku kaggle.json, więc wywołania kaggle CLI się nie powiodą.\n",
|
|
" - Na szczęście, Kaggle CLI umożliwia podanie danych uwierzytelniających w postaci zmiennych środowiskowych [link](https://github.com/Kaggle/kaggle-api#api-credentials):\n",
|
|
" ```bash\n",
|
|
"export KAGGLE_USERNAME=datadinosaur\n",
|
|
"export KAGGLE_KEY=xxxxxxxxxxxxxx\n",
|
|
" ```\n",
|
|
" - Jenkins natomiast umożliwia utworzenie parametru typu password, którego wartość nie jest nigdzie zapisywana (wartości pozostałych parametrów są zapisywane w zakładce \"Parameters\" każdego build-a, np. [tutaj](https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/hello-world-scripted/1/parameters/)\n",
|
|
" - konstukcja `withEnv` w Jenkinsfile, pozwala wywołać wszystkie otoczone nią polecenia z wyeksportowanymi wartościami zmiennych systemowych. Pozwala to np. przekazać wartości parametrów zadania Jenkinsowego do shella (poleceń wywoływanych z `sh`). \n",
|
|
" - ten sam rezultat co przy wykorzystaniu `withEnv` można by osiągnąć wywołując: `sh \"KAGGLE_USERNAME=${params.KAGGLE_USERNAME} KAGGLE_KEY=${params.KAGGLE_KEY} kaggle datasets list`, ale ten pierwszy wydahe się bardziej elegancki\n",
|
|
" - Poniżej przykładowy projekt, który pokazuje jak wywołać Kaggle CLI używając hasła podanego w parametrach zadania:\n",
|
|
" \n",
|
|
"https://tzietkiewicz.vm.wmi.amu.edu.pl:8080/job/kaggle-CLI-example/\n",
|
|
"```groovy\n",
|
|
"node {\n",
|
|
" stage('Preparation') { \n",
|
|
" properties([\n",
|
|
" parameters([\n",
|
|
" string(\n",
|
|
" defaultValue: 'tomaszzitkiewicz',\n",
|
|
" description: 'Kaggle username',\n",
|
|
" name: 'KAGGLE_USERNAME',\n",
|
|
" trim: false\n",
|
|
" ),\n",
|
|
" password(\n",
|
|
" defaultValue: '',\n",
|
|
" description: 'Kaggle token taken from kaggle.json file, as described in https://github.com/Kaggle/kaggle-api#api-credentials',\n",
|
|
" name: 'KAGGLE_KEY'\n",
|
|
" )\n",
|
|
" ])\n",
|
|
" ])\n",
|
|
" }\n",
|
|
" stage('Build') {\n",
|
|
" // Run the maven build\n",
|
|
" withEnv([\"KAGGLE_USERNAME=${params.KAGGLE_USERNAME}\",\n",
|
|
" \"KAGGLE_KEY=${params.KAGGLE_KEY}\" ]) {\n",
|
|
" sh 'echo KAGGLE_USERNAME: $KAGGLE_USERNAME'\n",
|
|
" sh 'kaggle datasets list'\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 7. Parametry zadania [1 pkt]\n",
|
|
"1. Dodaj do projektu `s123456-create-dataset` parametr teksotwy `CUTOFF`, który umożliwi zdefiniowanie wielkości odcięcia zbioru danych (czyli obetnie liczbę przykładów do `CUTOFF` pierwszych/losowych przykładów).\n",
|
|
"2. Wykorzystaj parametr w wywołaniu skryptu tworzącego zbiór\n",
|
|
"\n",
|
|
"- generowanie kodu definiującego parametry poprzez \"Pipeline syntax -> Snippet Generator\":\n",
|
|
" - wybierzz listy pozycji \"Properties: Set job properties\"\n",
|
|
" - zaznacz \"This project is parameterized\"\n",
|
|
" - Kliknij na \"Add parameter\" i wybierz rodzaj parametru"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"#### 6. Statystki [5 pkt]\n",
|
|
"Stwórz projekt (job) s123456-dataset-stats, który zrealizuje następujące kroki:\n",
|
|
" 1. Sklonuje repozytorium git \n",
|
|
" 2. Skopiuje zarchiwizowane pliki ze zbiorem danych z artefaktów projektu s123456-create-dataset\n",
|
|
" - użyj kroku [\"copyArtifacts\"](https://wiki.jenkins.io/display/JENKINS/Copy+Artifact+Plugin)\n",
|
|
" - możesz wygenerować potrzebny kod za pomocą generatorów w \"Pipeline Syntax\")\n",
|
|
" - dodaj paremetr typu \"Build selector for Copy artifact\", w którym będziesz mógł ustalić z którego builda zadania s123456-create-dataset chcesz skopiować artefakt. Wartość tego parametru będziesz musiał przekazać jako parametr `which build` -> \"Specified by a build parameter\"\n",
|
|
" - przykładowy kod copyArtifact:\n",
|
|
" ```groovy\n",
|
|
" copyArtifacts fingerprintArtifacts: true, projectName: 'MY_PROJECT', selector: buildParameter('BUILD_SELECTOR')\n",
|
|
" ```\n",
|
|
" - przykładowy kod definicji parametru:\n",
|
|
" ```groovy\n",
|
|
" properties([parameters([\n",
|
|
" buildSelector(\n",
|
|
" defaultSelector: lastSuccessful(),\n",
|
|
" description: 'Which build to use for copying artifacts',\n",
|
|
" name: 'BUILD_SELECTOR')\n",
|
|
" ])])\n",
|
|
" ```\n",
|
|
" 3. Wywoła skrypt shella (krok \"sh: Shell Script\"). \n",
|
|
" - Domyślnie tutaj znajdzie się wywołanie naszego skryptu liczącego statystyki.\n",
|
|
" - Ze względu na brakujące zależności, na razie wystarczy, że ten skrypt będzie \"liczył\" ilość linii w wejściowym pliku (polecenie \"wc -l\"). \n",
|
|
" - Skrypt powinien być zapisany w repozytorium. Unikamy wpisywania treści skryptów bezpośrednio w Jenkinsfile!\n",
|
|
" - Skrypt powinien zapisywać wyniki swojego działania do pliku\n",
|
|
" 4. Plik powstały w kroku 3. należy archiwizować (krok \"archiveArtifacts\")"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"author": "Tomasz Ziętkiewicz",
|
|
"celltoolbar": "Slideshow",
|
|
"email": "tomasz.zietkiewicz@amu.edu.pl",
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"lang": "pl",
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.9.1"
|
|
},
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
},
|
|
"subtitle": "3.CI-Jenkins[laboratoria]",
|
|
"title": "Inżynieria uczenia maszynowego",
|
|
"toc": {
|
|
"base_numbering": 1,
|
|
"nav_menu": {},
|
|
"number_sections": false,
|
|
"sideBar": false,
|
|
"skip_h1_title": false,
|
|
"title_cell": "Table of Contents",
|
|
"title_sidebar": "Contents",
|
|
"toc_cell": false,
|
|
"toc_position": {},
|
|
"toc_section_display": false,
|
|
"toc_window_display": false
|
|
},
|
|
"year": "2021"
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|