Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Some updates regarding workflows and continuous integration #17

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
# Reproducible Research

Booklet started with the Sigma team. Software engineering techniques applied to the reproductibility of scientific experiences and projects.
Software engineering techniques applied to the reproductibility of scientific experiences and projects.

This booklet started with the [SigMA](https://www.cristal.univ-lille.fr/?rubrique29&eid=30) team.

## Building this book

This booklet is build with [the latest version of pillar](https://github.com/pillar-markup/pillar/tree/newpipeline).

- To build this book, follow the installation notes of the "newpipeline" branch.
- Make sure you have a latex installation with all required dependencies.
- Make sure you have a LaTeX installation with all required dependencies.
- Finally on the root of the repository:

```bash
$ pillar build pdf
```

And you may have your results in the "_result/pdf" directory.
And you may have your results in the `_result/pdf directory.

## About Pillar Markup Syntax

The pillar markup syntax has been described in the following [cheatsheet](https://www.cheatography.com/benjaminvanryseghem/cheat-sheets/pillar/).
More info can be found in the pillar tutorial here:

https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/PillarChap/Pillar.html
More info can be found in the [pillar tutorial](https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/PillarChap/Pillar.html).
21 changes: 11 additions & 10 deletions continuous_integration.pillar
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@
This is always good practice to test some features of your application e.g. some functions, methods, etc.
And it is even better practice to guaranty the project will run under a given configuration i.e. a given OS' and associated packages' version.

Imagine you are developing on a Mac machine but wish your application to be run on Linux, too. Besides, your project may rely on many dependencies and some could even require to be compiled beforehand.
Now, imagine you are developing on a Mac machine but wish your application to be run on Linux, too. Besides, your project may rely on many dependencies and some could even require to be compiled beforehand.

Continuous integration tools e.g. *Travis>https://travis-ci.com/* or *Jenkins>https://jenkins.io/* will allow to automate these tasks and certify that your project can not only be run on your own machine but also under different configurations i.e. it is portable and your code is reproducible.
Continuous integration tools e.g. *Travis>https://travis-ci.com/* or *Jenkins>https://jenkins.io/* will allow you to automate these tasks and certify that your project can not only be run on your own machine but also under different configurations i.e. it is portable and your code is reproducible.

Once the configuration is set you can run a bunch of tests on your code and report the results to identify some bugs at different scales.
Once the configuration is set you can run a bunch of tests on your code and report the results to identify some bugs at different levels and scales.
This whole list of operations can be tested after every push or pull request

All this is performed on an remote machine that may be physically far distant from your personal computer.
You can configure the integration tool to execute this whole list of operations after each commit :)
@@note Keep in mind that all this is performed on an remote machine that may be physically far distant from your personal computer.

In this booklet we consider *Travis>https://travis-ci.com/*

!!! Configuration of Travis

The associated configuration file ==.travis.yml== collects all info required for testing the project on various configurations
The associated configuration file ==.travis.yml== collects all the information required for testing the project on various configurations

[[[language=yaml
language: python

sudo: require # In case you need to use apt-get

matrix: # matrix os/Python version
matrix: # matrix OS/Python version
include:
## Linux
- os: linux
Expand All @@ -45,12 +45,13 @@ install:
- pip install . # Install the project
]]]

@@note For more detailed information see the ''Getting started'' *tutorial>https://docs.travis-ci.com/user/getting-started/*
@@note For more detailed information see the Travis ''Getting started'' *tutorial>https://docs.travis-ci.com/user/getting-started/*

!!! Usecases of Travis
@continuous_integration_travis_usecases

- Check installation of the project of several machine configurations
- Test parts of code
- Build LaTex project
- Run unit tests and/or scripts
- Attach the ==.pdf== file to a ==tag== on GitHub after building the corresponding LaTeX project using Travis

See section *@workflows_for_researchers*
Binary file added figures/initialization_reproducible_paper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 46 additions & 23 deletions git_practical.pillar
Original file line number Diff line number Diff line change
Expand Up @@ -99,26 +99,32 @@ $ git reset --hard <commit_id>
$ git clean -df
]]]

The ==-d== option removes untracked directories in addition to untracked files, while the ==-f== option is a shortcut ==--force==, forcing the corresponding deletions.
The ==\-d== option removes untracked directories in addition to untracked files, while the ==\-f== option is a shortcut ==\-\-force==, forcing the corresponding deletions.

The reason for needing two commands instead of one relies on the fact that Git has several staging areas (such as the ones used to keep the tracked files), which we usually would like to clean when we discard the repository. Of course, experienced readers may search why they would need both in Git's documentation.
The reason for needing two commands instead of one relies on the fact that Git has several staging areas (such as the ones used to keep the tracked files), which we usually would like to clean when we discard the repository.
Of course, experienced readers may search why they would need both in Git's documentation.

@@todo what about *this>https://stackoverflow.com/a/21718540* ?

!!! Ignoring files (100%)
@gitignore

Many times we will find that we do not want to commit some files that are in our repository's directory. This is mostly the case of generated or automatically downloaded files. For example, imagine you have a C project and some makefiles to compile it, generating a binary library. While it would be good to store the result of compilation from time to time, storing it in a Git repository (or SVN, or Bazar) may be a cause of headaches. First, as you will see in *@expert_git*, this may be a cause for conflicts.
Many times we will find that we do not want to commit some files that are in our repository's directory.
This is mostly the case of generated or automatically downloaded files.
For example, imagine you have a C project and some makefiles to compile it, generating a binary library.
While it would be good to store the result of compilation from time to time, storing it in a Git repository (or SVN, or Bazar) may be a cause of headaches.
First, as you will see in *@expert_git*, this may be a cause for conflicts.
Second, since we should be able to generated such binary library from the sources, having the already compiled result in the repository does not add so much value.

This same ideas can be used to ignore any kind of generated file. For example, pdfs generated by document generation tools, meta-data files generated by IDEs and tools (e.g., Eclipse), compiled libraries (e.g., dll, so, or dylib files).
This same ideas can be used to ignore any kind of generated file.
For example, pdfs generated by document generation tools, meta-data files generated by IDEs and tools (e.g., Eclipse), compiled libraries (e.g., dll, so, or dylib files).

In such cases, we can tell Git to ignore cetain files using the ==.gitignore== file.
The ==.gitignore== file is an optional text file that we can write in the root of our repository with a list of file paths to ignore.

[[[
[[[language=bash
# Example of .gitignore file

$
# Lines starting with hashtags are comments

# A file name will ignore that file
Expand All @@ -138,14 +144,15 @@ $ git add .gitignore
$ git commit -m "Added gitignore"
]]]

From this moment on, all listed files will be ignored by ==git add== and ==git status==. And you will be able to perform further commands to add "all but ignored files":
From this moment on, all listed files will be ignored by ==git add== and ==git status==.
And you will be able to perform further commands to add "all but ignored files":

[[[language=bash
$ git add .
]]]

@@note If a file or a file type is tracked but you want git to ignore its changes afterward, adding it to .gitignore file will not make the job i.e. git will continue to track it.
To avoid keeping track of it in the future, but secure it locally in your working directory, it must be removed from the tracking list using ==git rm --cached <file> (.<file_type>)==.
To avoid keeping track of it in the future, but secure it locally in your working directory, it must be removed from the tracking list using ==git rm \-\-cached file #or *.file_type==.
Nevertheless, be aware that the file is still present in the past history!

@@todo Link to *@expert_git_remove_file* to remove a (sensitive) file from history
Expand All @@ -168,24 +175,33 @@ Think it this way: you need to tell the server who you are on every interaction
Otherwise, Github will reject any operation against your repository.
Such a setup requires the creation and uploading of SSH keys.

An SSH key works as a lock: a key is actually a pair of a public and a private key. The private key is meant to reside in your machine and not be published at all. A public key is meant to be shared with others to prove your identity. Whenever you want to prove your identity, SSH will exchange messages encrypted with your public key, and see if you are able to decrypt it using your private key.
An SSH key works as a lock: a key is actually a pair of a public and a private key.
The private key is meant to reside in your machine and not be published at all.
A public key is meant to be shared with others to prove your identity. Whenever you want to prove your identity, SSH will exchange messages encrypted with your public key, and see if you are able to decrypt it using your private key.

To create an SSH key, in *nix systems you can simply type in your terminal

[[[language=bash
$ ssh-keygen -t rsa -b 4096 -C "your_email@some_domain.com"
]]]

Follow the instructions in your terminal such as setting the location for your key pair (usually it is ==$HOME/.ssh==) and the passphrase (a kind of password). Finally, you'll end up with your public/private pair on the selected location. It is now time to upload it to Github.
Follow the instructions in your terminal such as setting the location for your key pair (usually it is ==$HOME/.ssh==) and the passphrase (a kind of password).
Finally, you'll end up with your public/private pair on the selected location. It is now time to upload it to Github.

Connect yourself to your Github settings (usually https://github.com/settings/profile) and go to the "SSH and GPG keys" menu. Import there the contents of your public key file. You should be now able to use your repository.
Connect yourself to your Github settings (usually https://github.com/settings/profile) and go to the "SSH and GPG keys" menu.
Import there the contents of your public key file. You should be now able to use your repository.

!!! Rewriting the history (Guille 100%)

Many times it happens that we accidentally commit something wrong.
Maybe we wanted to commit more or less things, maybe a completely different content, or we did a mistake in the commit's message. In these cases, we can rewrite Git's history, e.g, undo our current commit and go back to the previous commit, or rewrite the current commit with some new properties.
Maybe we wanted to commit more or less things, maybe a completely different content, or we did a mistake in the commit's message.
In these cases, we can rewrite Git's history, e.g, undo our current commit and go back to the previous commit, or rewrite the current commit with some new properties.

Be careful! Rewriting the history can have severe consequences. Imagine that the commit you want to undo was already pushed. This means that somebody else could have pulled this commit into her/his repository. If we undo this already publised commit, we are making everybody else's repositories obsolete! This can be indeed problematic depending on the number of users the project has, and their knowledge on Git to be able to solve this issue.
Be careful! Rewriting the history can have severe consequences.
Imagine that the commit you want to undo was already pushed.
This means that somebody else could have pulled this commit into her/his repository.
If we undo this already publised commit, we are making everybody else's repositories obsolete!
This can be indeed problematic depending on the number of users the project has, and their knowledge on Git to be able to solve this issue.

!!!! Undo a commit using ==git reset \-\-hard==

Expand All @@ -195,9 +211,11 @@ To undo the last commit, it is as easy as:
$ git reset --hard HEAD~1
]]]

==git reset \-\-hard [commitish]== makes your current branch point to [commitish]. ==HEAD== is your current head, and you can read ==~1== as \"minus one\". In other words, ==HEAD~1== is head minus one, which boils down to the parent of head, our previous commit.
==git reset \-\-hard [commitish]== makes your current branch point to [commitish]. ==HEAD== is your current head, and you can read ==~1== as \"minus one\".
In other words, ==HEAD~1== is head minus one, which boils down to the parent of head, our previous commit.

You can use this same trick to rewrite the history in any other way, since you can use any commitish expression to reset. For example, ==HEAD~17== means 17 versions before head, or ==someBranch~4== means four commits before the branch ==someBranch==.
You can use this same trick to rewrite the history in any other way, since you can use any commitish expression to reset.
For example, ==HEAD~17== means 17 versions before head, or ==someBranch~4== means four commits before the branch ==someBranch==.

!!!! Update a commit's message using ==git commit \-\-amend==

Expand All @@ -213,12 +231,15 @@ Or, if you don't use the ==\-m== option, a text editor will be prompt so you can
$ git commit --amend
]]]

You can use the same trick not only to modify a commit's message but to modify your entire commit. Actually, just adding new things with ==git add== before an ==\-\-amend== will replace the current commit with a new commit merging the previous commit changes with what you just added.
You can use the same trick not only to modify a commit's message but to modify your entire commit.
Actually, just adding new things with ==git add== before an ==\-\-amend== will replace the current commit with a new commit merging the previous commit changes with what you just added.

!!! How to overwrite/modify commits (Guillaume 100%)

!!! How to overwrite/modify commits (Guillaume 80%)
@@todo There's some overlap between this part and the previous one. Need to merge the 2 at some point

WARNING: It is highly not recommended to rewrite the history of a repo especially when part of it has already been pushed to a remote.
Modifying the history will most likely break the history shared by the different collaborators and you may deal with an inextricable merge conflict.
Modifying the history will most likely break the history shared by the different collaborators and you may deal with inextricable merge conflicts.

!!!! Change the last commit

Expand Down Expand Up @@ -254,7 +275,7 @@ f039832 Old
cca92f1 Even older
]]]

Then, you can interactively ==-i== focus on the last three ==HEAD~3== commit.
Then, you can interactively ==\-i== focus on the last three ==HEAD~3== commit.

[[[language=bash
$ git rebase -i HEAD~3
Expand All @@ -264,7 +285,7 @@ pick 71c0c64 Intermidiate
pick eae7846 New
]]]

@@note Observe that the commits are displayed in the reversed order.
@@note The list of commits are displayed in the descending.

Now you can squash the commit "Intermediate" into its parent commit "Old"

Expand Down Expand Up @@ -302,7 +323,9 @@ cca92f1 Even older

!!!! Pushing rewritten history

As soon as the history we have rewritten was never pushed before, we can continue working normally and pushing our changes then without problems. However, if we have already pushed the commit we want to undo, this means that we are potentially impacting all users of our repository. Because of the problems it can pose to other people, pushing a rewritten history is not a completely favoured by Git. Better said, it is not allowed by default and you'll be warned about it:
As long as the history we have rewritten has not been pushed yet, we can continue working normally and then think about pushing our changes with peace of mind.
However, if we have already pushed the commit we want to undo, we must face the dilemma of rewriting the history at the cost of potentially breaking other users' history and that would cause them many troubles (merge conflicts, ect.).
By default, ==git== does not allow this behaviour warns you about it:

[[[
$ git push
Expand All @@ -315,14 +338,14 @@ hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
]]]

With this message Git means that you should not blindly overwrite the history.
With this message ==git== means that you should not blindly overwrite the history.
Also, it suggests to pull changes from the remote repository.
However, doing that will bring back to our repository the history we wanted to undo!
What we want to do is to impose our current (undone) state in the remote repository.
To do that, we need to ""force"" the push using the ==git push \-\-force== or the ==git push \-f== option.

[[[
$git push -f
$ git push -f
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:REPOSITORY_OWNER/YOUR_REPOSITORY.git
+ a1713f3...6e0c7bf YOUR_BRANCH -> YOUR_BRANCH (forced update)
Expand Down
Loading