diff --git a/slides.ipynb b/slides.ipynb
index 621c198..ffed1b5 100644
--- a/slides.ipynb
+++ b/slides.ipynb
@@ -1,976 +1,1392 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# So, you want to go open Science ?\n",
+ "## Version, colaborate, share, test, document !\n",
+ "\n",
+ "
\n",
+ "\n",
+ "We will manly show you how to do things, and give you the full code of what we did\n",
+ "\n",
+ "
\n",
+ "\n",
+ "- https://c4science.ch/source/so-workshop/\n",
+ "- https://c4science.ch/source/so-slides/\n",
+ "\n",
+ "\n",
+ "
\n",
+ "SCITAS training with expertise from the EPFL Library
\n",
+ "Nicolas Richart and Jean-Baptiste Aubort - SCITAS"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# First thing first : Version your stuffs"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "# Create a repository\n",
+ "![](images/c4s-repository.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "## Some basics on git\n",
+ "- Let this represent a repository\n",
+ "![](images/git.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "- Clone an existing repository\n",
+ "![](images/git-clone.png)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 89,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "cd ..\n",
+ "rm -rf so-workshop"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 90,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Cloning into 'so-workshop'...\n",
+ "remote: Counting objects: 191, done.\u001b[K\n",
+ "remote: Compressing objects: 100% (181/181), done.\u001b[K\n",
+ "remote: Total 191 (delta 89), reused 0 (delta 0)\u001b[K\n",
+ "Receiving objects: 100% (191/191), 17.59 KiB | 2.20 MiB/s, done.\n",
+ "Resolving deltas: 100% (89/89), done.\n"
+ ]
+ }
+ ],
+ "source": [
+ "git clone https://c4science.ch/source/so-workshop.git\n",
+ "cd so-workshop"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 91,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "echo \"Add a modification to the readme\" >> README"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 92,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "On branch master\n",
+ "Your branch is up to date with 'origin/master'.\n",
+ "\n",
+ "Changes not staged for commit:\n",
+ " (use \"git add ...\" to update what will be committed)\n",
+ " (use \"git checkout -- ...\" to discard changes in working directory)\n",
+ "\n",
+ "\t\u001b[31mmodified: README\u001b[m\n",
+ "\n",
+ "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
+ ]
+ }
+ ],
+ "source": [
+ "# edit README\n",
+ "git status"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 93,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "git add README"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 94,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "On branch master\n",
+ "Your branch is up to date with 'origin/master'.\n",
+ "\n",
+ "Changes to be committed:\n",
+ " (use \"git reset HEAD ...\" to unstage)\n",
+ "\n",
+ "\t\u001b[32mmodified: README\u001b[m\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "git status"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 95,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[master 8971788] Added a change to README\n",
+ " 1 file changed, 1 insertion(+)\n"
+ ]
+ }
+ ],
+ "source": [
+ "git commit -m \"Added a change to README\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 96,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "* \u001b[33mcommit 89717881e7241f06a6731bd4211322bf7da72935\u001b[m\u001b[33m (\u001b[m\u001b[1;36mHEAD -> \u001b[m\u001b[1;32mmaster\u001b[m\u001b[33m)\u001b[m\u001b[m\n",
+ "\u001b[31m|\u001b[m Author: Nicolas Richart \u001b[m\n",
+ "\u001b[31m|\u001b[m Date: Mon Dec 3 04:32:43 2018 +0100\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "\u001b[31m|\u001b[m Added a change to README\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "* \u001b[33mcommit 59738410b9ec50d0a20cbdc5639e045084bbc5a1\u001b[m\u001b[33m (\u001b[m\u001b[1;31morigin/master\u001b[m\u001b[33m, \u001b[m\u001b[1;31morigin/HEAD\u001b[m\u001b[33m)\u001b[m\u001b[m\n",
+ "\u001b[31m|\u001b[m Author: Jean-Baptiste Aubort \u001b[m\n",
+ "\u001b[31m|\u001b[m Date: Fri Nov 30 16:52:44 2018 +0100\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "\u001b[31m|\u001b[m Fix branch name\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "* \u001b[33mcommit b896907f7b01e9490c47f85f57783cb36040c39d\u001b[m\u001b[m\n",
+ "\u001b[31m|\u001b[m Author: Jean-Baptiste Aubort \u001b[m\n",
+ "\u001b[31m|\u001b[m Date: Fri Nov 30 16:51:12 2018 +0100\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "\u001b[31m|\u001b[m Update branch names\u001b[m\n",
+ "\u001b[K\u001b[?1l\u001b>"
+ ]
+ }
+ ],
+ "source": [
+ "git log --graph -n3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 97,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Enumerating objects: 36, done.\n",
+ "Counting objects: 100% (36/36), done.\n",
+ "Delta compression using up to 4 threads\n",
+ "Compressing objects: 100% (23/23), done.\n",
+ "Writing objects: 100% (36/36), 3.68 KiB | 3.68 MiB/s, done.\n",
+ "Total 36 (delta 6), reused 28 (delta 5)\n",
+ "To ssh://c4science.ch/source/so-workshop-test.git\n",
+ " + 1294907...8971788 master -> master (forced update)\n",
+ "Branch 'master' set up to track remote branch 'master' from 'origin'.\n"
+ ]
+ }
+ ],
+ "source": [
+ "# In order to push without changing the repository origin\n",
+ "git remote set-url origin ssh://git@c4science.ch/source/so-workshop-test.git\n",
+ "git push --force -u origin master"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "- `git commit`\n",
+ "![](images/git-commit.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "- often someone else already commited\n",
+ "![](images/git-commit-remote.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "- `git pull`\n",
+ "![](images/git-pull.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "- `git push`\n",
+ "![](images/git-push.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# Collaborate through projects"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "## Why projects\n",
+ "\n",
+ "- To tidy your repositories\n",
+ "- To handle permissions\n",
+ "- To define tasks\n",
+ "- To attach information"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# Now that your are all setup : add a workflow"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "-"
+ }
+ },
+ "source": [
+ "## Why a workflow\n",
+ "\n",
+ "- Helps to separate development\n",
+ "- Helps to release a code\n",
+ "- Helps to review to code\n",
+ "- Helps to maintain different versions"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "## Minimalist workflow\n",
+ "\n",
+ "- Feature branches"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 98,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Switched to a new branch 'feature/workflow'\n"
+ ]
+ }
+ ],
+ "source": [
+ "git checkout -b feature/workflow"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 99,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[feature/workflow cd9f182] Added a new feature to demonstrate a simple workflow\n",
+ " 1 file changed, 1 insertion(+)\n",
+ " create mode 100644 new_feature\n"
+ ]
+ }
+ ],
+ "source": [
+ "echo \"Adding my feature\" >> new_feature\n",
+ "git add new_feature\n",
+ "git commit -m \"Added a new feature to demonstrate a simple workflow\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "- Merge your changes back in master"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 100,
+ "metadata": {
+ "autoscroll": false,
+ "ein.hycell": false,
+ "ein.tags": "worksheet-0",
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Switched to branch 'master'\n",
+ "Your branch is up to date with 'origin/master'.\n",
+ "Merge made by the 'recursive' strategy.\n",
+ " new_feature | 1 \u001b[32m+\u001b[m\n",
+ " 1 file changed, 1 insertion(+)\n",
+ " create mode 100644 new_feature\n"
+ ]
+ }
+ ],
+ "source": [
+ "git checkout master\n",
+ "git merge --no-ff --no-edit feature/workflow"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 101,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "* \u001b[33mcommit 19f5c5ca82998d3259cd80df70e770cbf07c56f9\u001b[m\u001b[33m (\u001b[m\u001b[1;36mHEAD -> \u001b[m\u001b[1;32mmaster\u001b[m\u001b[33m)\u001b[m\u001b[m\n",
+ "\u001b[31m|\u001b[m\u001b[32m\\\u001b[m Merge: 8971788 cd9f182\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[32m|\u001b[m Author: Nicolas Richart \u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[32m|\u001b[m Date: Mon Dec 3 04:32:47 2018 +0100\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[32m|\u001b[m \u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[32m|\u001b[m Merge branch 'feature/workflow'\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[32m|\u001b[m \u001b[m\n",
+ "\u001b[31m|\u001b[m * \u001b[33mcommit cd9f182ab178f62d1cfb8a1dee43e3bc80ca11fb\u001b[m\u001b[33m (\u001b[m\u001b[1;32mfeature/workflow\u001b[m\u001b[33m)\u001b[m\u001b[m\n",
+ "\u001b[31m|\u001b[m\u001b[31m/\u001b[m Author: Nicolas Richart \u001b[m\n",
+ "\u001b[31m|\u001b[m Date: Mon Dec 3 04:32:47 2018 +0100\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "\u001b[31m|\u001b[m Added a new feature to demonstrate a simple workflow\u001b[m\n",
+ "\u001b[31m|\u001b[m \u001b[m\n",
+ "* \u001b[33mcommit 89717881e7241f06a6731bd4211322bf7da72935\u001b[m\u001b[33m (\u001b[m\u001b[1;31morigin/master\u001b[m\u001b[33m, \u001b[m\u001b[1;31morigin/HEAD\u001b[m\u001b[33m)\u001b[m\u001b[m\n",
+ "\u001b[32m|\u001b[m Author: Nicolas Richart \u001b[m\n",
+ "\u001b[32m|\u001b[m Date: Mon Dec 3 04:32:43 2018 +0100\u001b[m\n",
+ "\u001b[32m|\u001b[m \u001b[m\n",
+ "\u001b[32m|\u001b[m Added a change to README\u001b[m\n",
+ "\u001b[K\u001b[?1l\u001b>"
+ ]
+ }
+ ],
+ "source": [
+ "git log --graph -n3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 102,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Already on 'master'\n",
+ "Your branch is ahead of 'origin/master' by 2 commits.\n",
+ " (use \"git push\" to publish your local commits)\n",
+ "Enumerating objects: 5, done.\n",
+ "Counting objects: 100% (5/5), done.\n",
+ "Delta compression using up to 4 threads\n",
+ "Compressing objects: 100% (3/3), done.\n",
+ "Writing objects: 100% (4/4), 413 bytes | 413.00 KiB/s, done.\n",
+ "Total 4 (delta 2), reused 0 (delta 0)\n",
+ "To ssh://c4science.ch/source/so-workshop-test.git\n",
+ " 8971788..19f5c5c master -> master\n"
+ ]
+ }
+ ],
+ "source": [
+ "git checkout master \n",
+ "git push"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ " - Review the code using `arcanist`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 103,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Switched to a new branch 'feature/review'\n",
+ "[feature/review a00f49c] Added a new feature to demonstrate a review\n",
+ " 1 file changed, 1 insertion(+)\n",
+ "[feature/review 71efe12] Adding a file\n",
+ " 1 file changed, 0 insertions(+), 0 deletions(-)\n",
+ " create mode 100644 new_file\n"
+ ]
+ }
+ ],
+ "source": [
+ "git checkout -b feature/review\n",
+ "echo \"Adding my feature that needs review\" >> new_feature\n",
+ "git add new_feature\n",
+ "git commit -m \"Added a new feature to demonstrate a review\"\n",
+ "touch new_file\n",
+ "git add new_file\n",
+ "git commit -m \"Adding a file\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 104,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "cat > ../.arcmessage << EOF\n",
+ "Adding a reviewed feature\n",
+ "Test Plan: none yet\n",
+ "Reviewers: nrichart\n",
+ "EOF\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 105,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Linting...\n",
+ "No lint engine configured for this project.\n",
+ "Running unit tests...\n",
+ "No unit test engine is configured for this project.\n",
+ "\u001b[44m\u001b[1m SKIP STAGING \u001b[m\u001b[49m No staging area is configured for this repository.\n",
+ "Created a new Differential revision:\n",
+ " \u001b[1mRevision URI:\u001b[m \u001b[4mhttps://c4science.ch/D220\u001b[m\n",
+ "\n",
+ "Included changes:\n",
+ " M new_feature\n",
+ " A new_file\n"
+ ]
+ }
+ ],
+ "source": [
+ "arc diff master -F ../.arcmessage --no-amend"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "![](images/c4s-differencial.png)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "- Once the review accepted it can be landed"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 108,
+ "metadata": {
+ "scrolled": true,
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Landing current branch 'feature/review'.\n",
+ "\u001b[44m\u001b[1m TARGET \u001b[m\u001b[49m Landing onto \"master\", the default target under git.\n",
+ "\u001b[44m\u001b[1m REMOTE \u001b[m\u001b[49m Using remote \"origin\", the default remote under git.\n",
+ "\u001b[44m\u001b[1m FETCH \u001b[m\u001b[49m Fetching origin/master...\n",
+ "These commits will be landed:\n",
+ "\n",
+ " - 71efe12 Adding a file\n",
+ " - a00f49c Added a new feature to demonstrate a review\n",
+ "\n",
+ "Landing revision 'D220: Adding a reviewed feature'...\n",
+ "\u001b[1m\u001b[42m BUILDS PASSED \u001b[49m\u001b[m Harbormaster builds for the active diff completed successfully.\n",
+ "\u001b[44m\u001b[1m PUSHING \u001b[m\u001b[49m Pushing changes to \"origin/master\".\n",
+ "Enumerating objects: 9, done.\n",
+ "Counting objects: 100% (9/9), done.\n",
+ "Delta compression using up to 4 threads\n",
+ "Compressing objects: 100% (6/6), done.\n",
+ "Writing objects: 100% (7/7), 677 bytes | 225.00 KiB/s, done.\n",
+ "Total 7 (delta 4), reused 0 (delta 0)\n",
+ "To ssh://c4science.ch/source/so-workshop-test.git\n",
+ " 19f5c5c..52ec4a6 52ec4a6c006cd9b0b95957dc810d98bc2cc84139 -> master\n",
+ "\u001b[44m\u001b[1m UPDATE \u001b[m\u001b[49m Local \"master\" tracks target remote \"origin/master\", checking out and pulling changes.\n",
+ "\u001b[44m\u001b[1m PULL \u001b[m\u001b[49m Checking out and pulling \"master\".\n",
+ "Cleaning up branch \"feature/review\"...\n",
+ "(Use `git checkout -b feature/review 71efe12719648965e96ad146412d0c3726dc79a0` if you want it back.)\n",
+ "\u001b[42m\u001b[1m DONE \u001b[m\u001b[49m Landed changes.\n"
+ ]
+ }
+ ],
+ "source": [
+ "arc land --merge --revision D220"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "subslide"
+ }
+ },
+ "source": [
+ "## Adding a public verison of the code"
+ ]
+ },
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 117,
"metadata": {
"slideshow": {
- "slide_type": "skip"
+ "slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Switched to branch 'master'\n",
- "Your branch is up to date with 'origin/master'.\n",
- "Already up to date.\n"
+ "warning: no common commits\n",
+ "remote: Enumerating objects: 3, done.\u001b[K\n",
+ "remote: Counting objects: 100% (3/3), done.\u001b[K\n",
+ "remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0\u001b[K\n",
+ "Unpacking objects: 100% (3/3), done.\n",
+ "From github.com:nrichart/so-workshop\n",
+ " * [new branch] master -> public/master\n"
]
}
],
"source": [
- "cd ../so-workshop\n",
- "git checkout master\n",
- "git pull"
+ "git remote add public git@github.com:nrichart/so-workshop.git\n",
+ "git fetch public"
]
},
{
- "cell_type": "markdown",
+ "cell_type": "code",
+ "execution_count": 119,
"metadata": {
"slideshow": {
- "slide_type": "slide"
+ "slide_type": "fragment"
}
},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Branch 'public' set up to track remote branch 'master' from 'public'.\n",
+ "Switched to a new branch 'public'\n"
+ ]
+ }
+ ],
"source": [
- "# So, you want to go open Science ?\n",
- "## Testing, testing, testing !\n",
- "\n",
- "
\n",
- "\n",
- "- https://c4science.ch/source/so-workshop/\n",
- "- https://c4science.ch/source/so-slides/\n",
- "\n",
- "
\n",
- "SCITAS training with expertise from the EPFL Library
\n",
- "Nicolas Richart and Jean-Baptiste Aubort - SCITAS"
+ "git checkout -b public public/master"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 122,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Squash commit -- not updating HEAD\n",
+ "Automatic merge went well; stopped before committing as requested\n"
+ ]
+ }
+ ],
+ "source": [
+ "git merge --squash --allow-unrelated-histories master"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 125,
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "On branch public\n",
+ "Your branch is ahead of 'public/master' by 1 commit.\n",
+ " (use \"git push\" to publish your local commits)\n",
+ "\n",
+ "nothing to commit, working tree clean\n",
+ "Enumerating objects: 9, done.\n",
+ "Counting objects: 100% (9/9), done.\n",
+ "Delta compression using up to 4 threads\n",
+ "Compressing objects: 100% (5/5), done.\n",
+ "Writing objects: 100% (8/8), 885 bytes | 885.00 KiB/s, done.\n",
+ "Total 8 (delta 0), reused 2 (delta 0)\n",
+ "To github.com:nrichart/so-workshop.git\n",
+ " cb63ebe..01b2301 public -> master\n",
+ "Branch 'public' set up to track remote branch 'master' from 'public'.\n"
+ ]
+ }
+ ],
+ "source": [
+ "git commit -m \"First public revision\"\n",
+ "git push -u public public:master"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Continuous Integration (CI)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"## What is CI ?\n",
"\n",
"- Automation of build and tests\n",
"- Run tests at each commit\n",
"- You need to write tests !"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"## Why use CI ?\n",
"\n",
"- Detect bugs when they are introduced\n",
"- Detect when fixed bugs appear again (regression)\n",
"- Publish code that works"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Ensure code has a certain quality level\n",
"- Linters\n",
"- Test Coverage"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Jenkins on c4science"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## https://c4science.ch/jobs\n",
"![](images/c4s-jenkinsjob.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## https://jenkins.c4science.ch/\n",
"![](images/c4s-jenkins.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Example\n",
"## Jenkins base"
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Switched to branch 'feature/jenkins-base'\n",
- "Your branch is up to date with 'origin/feature/jenkins-base'.\n",
- "\u001b[01;34m.\u001b[00m\n",
- "├── \u001b[01;34mcode\u001b[00m\n",
- "│ ├── mylib.py\n",
- "│ └── \u001b[01;32mtest.py\u001b[00m\n",
- "├── Jenkinsfile\n",
- "└── README\n",
- "\n",
- "1 directory, 4 files\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"git checkout feature/jenkins-base\n",
"tree"
]
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "#!/usr/bin/env python3\n",
- "\n",
- "class MyLib():\n",
- "\n",
- " def __init__(self):\n",
- " pass\n",
- "\n",
- " def MyFunc(self):\n",
- " return 'test'\n",
- "\n",
- "if __name__ == '__main__':\n",
- " pass\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat code/mylib.py"
]
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "#!/usr/bin/env python3\n",
- "import unittest, pytest\n",
- "import mylib\n",
- "\n",
- "class Test(unittest.TestCase):\n",
- "\n",
- " def test_return(self):\n",
- " m = mylib.MyLib()\n",
- " self.assertTrue(m.MyFunc() == 'test')\n",
- "\n",
- "if __name__ == '__main__':\n",
- " pytest.main(['./test.py'])\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat code/test.py"
]
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "pipeline {\n",
- "\n",
- " agent {\n",
- " docker {\n",
- " image 'python:3.7'\n",
- " }\n",
- " }\n",
- "\n",
- " environment {\n",
- " HOME = \"$WORKSPACE\"\n",
- " }\n",
- "\n",
- " stages {\n",
- " stage('install dependencies') {\n",
- " steps {\n",
- " sh 'pip3 install --user pytest'\n",
- " }\n",
- " }\n",
- " stage('run tests') {\n",
- " steps {\n",
- " sh '$HOME/.local/bin/pytest code/test.py'\n",
- " }\n",
- " }\n",
- " }\n",
- "\n",
- "}\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat Jenkinsfile"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![](images/jenkins-base.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Example\n",
"## Jenkins dockerfile"
]
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Switched to branch 'feature/jenkins-dockerfile'\n",
- "Your branch is up to date with 'origin/feature/jenkins-dockerfile'.\n",
- "\u001b[01;34m.\u001b[00m\n",
- "├── \u001b[01;34mcode\u001b[00m\n",
- "│ ├── mylib.py\n",
- "│ └── \u001b[01;32mtest.py\u001b[00m\n",
- "├── Dockerfile\n",
- "├── Jenkinsfile\n",
- "└── README\n",
- "\n",
- "1 directory, 5 files\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"git checkout feature/jenkins-dockerfile\n",
"tree"
]
},
{
"cell_type": "code",
- "execution_count": 19,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "FROM python:3.7\n",
- "RUN pip3 install --no-cache-dir pytest\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat Dockerfile"
]
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "pipeline {\n",
- "\n",
- " agent {\n",
- " dockerfile true \n",
- " }\n",
- "\n",
- " stages {\n",
- " stage('run tests') {\n",
- " steps {\n",
- " sh 'pytest code/test.py'\n",
- " }\n",
- " }\n",
- " }\n",
- "\n",
- "}\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat Jenkinsfile"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Example\n",
"### Jenkins junit"
]
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Switched to branch 'feature/jenkins-junit'\n",
- "Your branch is up to date with 'origin/feature/jenkins-junit'.\n",
- "\u001b[01;34m.\u001b[00m\n",
- "├── \u001b[01;34mcode\u001b[00m\n",
- "│ ├── mylib.py\n",
- "│ └── \u001b[01;32mtest.py\u001b[00m\n",
- "├── Dockerfile\n",
- "├── Jenkinsfile\n",
- "└── README\n",
- "\n",
- "1 directory, 5 files\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"git checkout feature/jenkins-junit\n",
"tree"
]
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "pipeline {\n",
- "\n",
- " agent {\n",
- " dockerfile true \n",
- " }\n",
- "\n",
- " stages {\n",
- " stage('run tests') {\n",
- " steps {\n",
- " sh 'pytest --junitxml results.xml code/test.py'\n",
- " }\n",
- " }\n",
- " }\n",
- "\n",
- " post {\n",
- " always {\n",
- " junit 'results.xml'\n",
- " }\n",
- " }\n",
- "\n",
- "}\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat Jenkinsfile"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![](images/jenkins-junit.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![](images/jenkins-junit2.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# C4science\n",
"## Arcanist\n",
"Command line tool to interact with c4science"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"### Linters\n",
"\n",
"> A linter or lint refers to tools that analyze source code to flag programming errors, bugs, stylistic errors, and suspicious constructs.\n",
"\n",
"- https://en.wikipedia.org/wiki/Lint_(software)\n",
"- https://c4science.ch/w/c4science/lint/"
]
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Switched to branch 'feature/arcanist-linter'\n",
- "Your branch is up to date with 'origin/feature/arcanist-linter'.\n",
- "\u001b[01;34m.\u001b[00m\n",
- "├── .arclint\n",
- "├── \u001b[01;34mcode\u001b[00m\n",
- "│ ├── mylib.py\n",
- "│ └── \u001b[01;32mtest.py\u001b[00m\n",
- "├── Dockerfile\n",
- "├── .gitignore\n",
- "├── Jenkinsfile\n",
- "└── README\n",
- "\n",
- "1 directory, 7 files\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"git checkout feature/arcanist-linter\n",
"tree -a -I \".git\""
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[42m\u001b[1m CONFIGURED \u001b[m\u001b[49m \u001b[1mtext\u001b[m (Basic Text Linter)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mcsharp\u001b[m (C#)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mcpplint\u001b[m (C++ Google's Styleguide)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mcppcheck\u001b[m (C++ linter)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mlessc\u001b[m (CSS pre-processor)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mcsslint\u001b[m (CSSLint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mchmod\u001b[m (Chmod)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mgjslint\u001b[m (Closure Linter)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mcoffeelint\u001b[m (CoffeeLint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mcomposer\u001b[m (Composer Dependency Manager)\n",
- "\u001b[42m\u001b[1m CONFIGURED \u001b[m\u001b[49m \u001b[1mfilename\u001b[m (Filename)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mgenerated\u001b[m (Generated Code)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mgolint\u001b[m (Golint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mhlint\u001b[m (Haskell Linter)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mjsonlint\u001b[m (JSON Lint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mjson\u001b[m (JSON Lint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mjscs\u001b[m (JavaScript Code Style)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mjshint\u001b[m (JavaScript error checking)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mnolint\u001b[m (Lint Disabler)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mmerge-conflict\u001b[m (Merge Conflicts)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mphpcs\u001b[m (PHP_CodeSniffer)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mphutil-library\u001b[m (Phutil Library Linter)\n",
- "\u001b[42m\u001b[1m CONFIGURED \u001b[m\u001b[49m \u001b[1mpylint\u001b[m (PyLint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mflake8\u001b[m (Python Flake8 multi-linter)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mpep8\u001b[m (Python PEP 8)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mpyflakes\u001b[m (Python PyFlakes)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mruby\u001b[m (Ruby)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mrubocop\u001b[m (Ruby static code analyzer)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mscript-and-regex\u001b[m (Script and Regex)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mxml\u001b[m (SimpleXML Linter)\n",
- "\u001b[42m\u001b[1m CONFIGURED \u001b[m\u001b[49m \u001b[1mspelling\u001b[m (Spellchecker)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mxhpast\u001b[m (XHPAST Lint)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mphp\u001b[m (php -l)\n",
- "\u001b[43m\u001b[1m AVAILABLE \u001b[m\u001b[49m \u001b[1mpuppet-lint\u001b[m (puppet-lint)\n",
- "(Run `arc linters --verbose` for more details.)\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"arc linters"
]
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"linters\": {\n",
- " \"spelling-linter\": {\n",
- " \"type\": \"spelling\"\n",
- " },\n",
- " \"filename-linter\": {\n",
- " \"type\": \"filename\"\n",
- " },\n",
- " \"text-linter\": {\n",
- " \"type\": \"text\"\n",
- " },\n",
- " \"python-checks\": {\n",
- " \"type\": \"pylint\",\n",
- " \"include\": \"(\\\\.py$)\"\n",
- " }\n",
- " }\n",
- "}\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat .arclint"
]
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Jenkinsfile:4:Auto-Fix: Trailing Whitespace\n",
- "README:3:Auto-Fix: Trailing Whitespace at EOF\n",
- "code/mylib.py:1:Advice: Missing Docstring\n",
- "code/mylib.py:3:Advice: Missing Docstring\n",
- "code/mylib.py:3:Advice: Old Style Class\n",
- "code/mylib.py:8:Advice: Invalid Name\n",
- "code/mylib.py:8:Advice: Missing Docstring\n",
- "code/mylib.py:8:Advice: No Self Use\n",
- "code/mylib.py:11:Advice: Invalid Name\n",
- "code/mylib.py:11:Advice: Missing Docstring\n",
- "code/mylib.py:11:Advice: No Self Use\n",
- "code/test.py:1:Advice: Missing Docstring\n",
- "code/test.py:5:Advice: Missing Docstring\n",
- "code/test.py:9:Advice: Missing Docstring\n",
- "code/test.py:12:Warning: Mixed Indentation\n",
- "code/test.py:12:Error: Tab Literal\n",
- "code/test.py:12:Advice: Missing Docstring\n",
- "code/test.py:12:Warning: Unused Variable\n",
- "code/test.py:13:Warning: Mixed Indentation\n"
- ]
- },
- {
- "ename": "",
- "evalue": "2",
- "output_type": "error",
- "traceback": []
- }
- ],
+ "outputs": [],
"source": [
"arc lint --never-apply-patches --output summary --everything"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Arcanist\n",
"### Unit-Tests\n",
"Using the TAP (Test Anything Protocol) extension of Arcanist, we can report test units result to c4science"
]
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Switched to branch 'feature/arcanist-unittests'\n",
- "Your branch is up to date with 'origin/feature/arcanist-unittests'.\n",
- "Submodule path '.arcanist-extensions': checked out 'b89c749a90154676967a1601b62563fed0cbd572'\n",
- "\u001b[01;34m.\u001b[00m\n",
- "├── .arcconfig\n",
- "├── .arclint\n",
- "├── \u001b[01;34mcode\u001b[00m\n",
- "│ ├── mylib.py\n",
- "│ └── \u001b[01;32mtest.py\u001b[00m\n",
- "├── Dockerfile\n",
- "├── .gitignore\n",
- "├── .gitmodules\n",
- "├── Jenkinsfile\n",
- "└── README\n",
- "\n",
- "1 directory, 9 files\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"git checkout feature/arcanist-unittests\n",
"git submodule update --init\n",
"tree -a -I \".git|.arcanist-extensions\""
]
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"load\": [\n",
- " \".arcanist-extensions/tap_test_engine\"\n",
- " ],\n",
- "\n",
- " \"unit.engine\": \"TAPTestEngine\",\n",
- " \"unit.engine.tap.command\": \"code/test.py\"\n",
- "}\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat .arcconfig"
]
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ok 1 - Test.test_capitalize\n",
- "ok 2 - Test.test_return\n",
- "1..2\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"pytest --tap-stream ./code/test.py"
]
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ok 1 - Test.test_capitalize\n",
- "not ok 2 - Test.test_capitalize_fail\n",
- "# \n",
- "# self = \n",
- "# \n",
- "# def test_capitalize_fail(self):\n",
- "# > self.assertTrue(self.m.Capitalize('TeSt') == 'test')\n",
- "# E AssertionError: False is not true\n",
- "# \n",
- "# code/test.py:16: AssertionError\n",
- "ok 3 - Test.test_return\n",
- "1..3\n",
- " \u001b[42m\u001b[1m PASS \u001b[m\u001b[49m \u001b[32m <1ms\u001b[39m\u001b[33m★\u001b[39m Test.test_capitalize\n",
- " \u001b[41m\u001b[1m FAIL \u001b[m\u001b[49m Test.test_capitalize_fail\n",
- "#\n",
- " \u001b[42m\u001b[1m PASS \u001b[m\u001b[49m \u001b[32m <1ms\u001b[39m\u001b[33m★\u001b[39m Test.test_return\n"
- ]
- },
- {
- "ename": "",
- "evalue": "2",
- "output_type": "error",
- "traceback": []
- }
- ],
+ "outputs": [],
"source": [
"arc unit --rev HEAD^"
]
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "FROM dkdde/arcanist\n",
- "RUN apk add --update bash \\\n",
- " git \\\n",
- " php7 \\\n",
- " php7-curl \\\n",
- " php7-json \\\n",
- " py2-pip \\\n",
- " && pip install pytest pytest-tap tap.py \\\n",
- " && rm -rf /var/cache/apk/*\n",
- "RUN ln -s /arc/arcanist/bin/arc /bin/arc\n",
- "\n",
- "ENTRYPOINT []\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat Dockerfile"
]
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "pipeline {\n",
- "\n",
- " agent {\n",
- " dockerfile true\n",
- " }\n",
- "\n",
- " stages {\n",
- " stage('run tests') {\n",
- " steps {\n",
- " sh 'git submodule update --init'\n",
- " sh 'arc unit --rev HEAD^'\n",
- " }\n",
- " }\n",
- " }\n",
- "\n",
- " post {\n",
- " always {\n",
- " archiveArtifacts artifacts: '*.tap'\n",
- " step([$class: \"TapPublisher\", testResults: \"*.tap\"])\n",
- " }\n",
- " }\n",
- "\n",
- "}\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"cat Jenkinsfile"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"![](images/jenkins-tap.png)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# That's all folks !\n",
"## Explore, Experiment and Test !\n",
"# Questions ?"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Bash",
"language": "bash",
"name": "bash"
},
"language_info": {
"codemirror_mode": "shell",
"file_extension": ".sh",
"mimetype": "text/x-sh",
"name": "bash"
},
"livereveal": {
"height": 768,
"theme": "serif",
"transition": "none",
"width": 1024
}
},
"nbformat": 4,
"nbformat_minor": 2
}