Wednesday, October 31, 2018

Remove one file from git commit to a remote branch

Ooops, I did it again. Commited and pushed one file too much.
? git push --set-upstream origin bugfix/JRASERVER-65811
What now? How to remove the file from a public commit?

Let's first go back to the base branch.
? git checkout -
Switched to branch 'develop'
Your branch is up to date with 'origin/develop'.
I assume I may have some changes in my local copy so first need to clean it. I am going to delete my local branch.
? git branch -D bugfix/JRASERVER-65811
Deleted branch bugfix/JRASERVER-65811 (was 5e17f72f).
Next step is to synchronize with remote repository and fetch the branch again.
? git pull
remote: Enumerating objects: 119, done.
remote: Counting objects: 100% (119/119), done.
remote: Compressing objects: 100% (119/119), done.
remote: Total 119 (delta 41), reused 0 (delta 0)
Receiving objects: 100% (119/119), 43.63 KiB | 1.82 MiB/s, done.
Resolving deltas: 100% (41/41), done.
From gitlab:project/frontend
   736ac14a..ea0ba57e  bugfix/JRASERVER-65811-allopenissues -> origin/bugfix/JRASERVER-65811-allopenissues
Already up to date.
I can now switch to the branch back.
? git checkout bugfix/JRASERVER-65811
Switched to a new branch 'bugfix/JRASERVER-65811'
Branch 'bugfix/JRASERVER-65811' set up to track remote branch 'bugfix/JRASERVER-65811' from 'origin'.
Time to bring the last commit into staging.
? git reset --soft HEAD^
I can see this was done by showing status.
? git status
On branch bugfix/JRASERVER-65811
Your branch is behind 'origin/bugfix/JRASERVER-65811' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes to be committed:
  (use "git reset HEAD ..." to unstage)

        new file:   src/app/lktree/lktree.component.spec.ts
        modified:   src/app/modules/spaces/data/space-datasource.ts
        modified:   src/app/modules/spaces/document-details/document-details.component.html
        modified:   src/app/modules/spaces/spaces-tree/spaces-tree.component.ts
        modified:   src/app/modules/user-context/data/user-context-datasource.ts
The first of files is the one I want to extract and unstage from to working copy. This simply undo git add.
? git reset src/app/lktree/lktree.component.spec.ts
Yeah! My changes are now in state I wanted!
? git status
On branch bugfix/JRASERVER-65811
Your branch is behind 'origin/bugfix/JRASERVER-65811' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes to be committed:
  (use "git reset HEAD ..." to unstage)

        modified:   src/app/modules/spaces/data/space-datasource.ts
        modified:   src/app/modules/spaces/document-details/document-details.component.html
        modified:   src/app/modules/spaces/spaces-tree/spaces-tree.component.ts
        modified:   src/app/modules/user-context/data/user-context-datasource.ts

Untracked files:
  (use "git add ..." to include in what will be committed)

I can commit again - this time the right files.
? git commit src/app/modules/spaces/ src/app/modules/user-context/data/user-context-datasource.ts -m "JRASERVER-65811: allopenissues"
[bugfix/JRASERVER-65811 80002b42] JRASERVER-65811: allopenissues
 4 files changed, 60 insertions(+), 25 deletions(-)
Last commit is to overwrite the remote branch. Do not do it at home ;)
? git push --force

Friday, June 22, 2018

Authenticating with deploy keys in Jenkins pipelines

While using M$ github you may use deploy keys dedicated to a specific repository instead of giving your private key to Jenkins. And yes, it is possible to use deploy key in Jenkins pipelines.

To be able to manage your ssh identity you need first to install sshagent plugin.

BTW If you are running Jenkins instance on M$ windows machine remember to add sshagent (eg. from your git distribution) to your %PATH%.

Generate a key pair.
ssh-keygen -t rsa -b 4096 -C ""

Goto Credentials in Jenkins left-side main menu. Add credentials of type 'SSH Username with private key'. You can paste the created private key into text area.

In M$ github repository settings now you can add corresponding public key.

In your pipeline code you can use credentials when you surround eg. git calls with sshagent block.

                sshagent(credentials: ['throw-me-away-key']) {
                    bat """git pull origin master"""

If you get errors make sure that you are not using friendly name but right ID of credential in Jenkins.

10:09:04 FATAL: [ssh-agent] Could not find specified credentials
10:09:04 [ssh-agent] Looking for ssh-agent implementation...
10:09:04 [ssh-agent]   Exec ssh-agent (binary ssh-agent on a remote machine)
10:09:04 $ ssh-agent
10:09:04 SSH_AUTH_SOCK=/tmp/ssh-vCKYmwW5gfvP/agent.5592
10:09:04 SSH_AGENT_PID=5572
10:09:04 [ssh-agent] Started.
10:09:04 [original] Running batch script
10:09:04 C:\Program Files (x86)\Jenkins\workspace\lk-pipeline-0\original>git pull 
10:09:06 $ ssh-agent -k
10:09:06 Permission denied (publickey).
10:09:06 fatal: Could not read from remote repository.
10:09:06 Please make sure you have the correct access rights
10:09:06 and the repository exists.
10:09:06 unset SSH_AUTH_SOCK;
10:09:06 unset SSH_AGENT_PID;
10:09:06 echo Agent pid 5572 killed;
10:09:06 [ssh-agent] Stopped.

Friday, January 12, 2018

OOP is not dead: Elegant Objects

Recently I have observed a growing wave of what I describe as kind of anti-design movement. Experienced people find out they have been doing it wrong. One say: TDD is dead, other: we do not need interfaces. Script kiddies Dynamic language programmers claim strongly typed languages are broken. It comes even to a very last discovery that short methods are pure evil!
I've just spoken to a programmer, who had nearly 20 years of experience with Java, yet trying to convince me that interfaces are useless, just because for that long time he had never written an alternative implementation of method. In same conversation however, he praised ORMs for possibility of painless exchanging of DB engine!
The leitmotiv of this new heresy is that we can easily cut off the effort introduced by OOP, design patterns, TDD, DDD or any other, until now considered a good practice and focus on delivering just what matters - the `business value` itself. So that we can successfully bill the client and go to the next project. This sounds good. That may make sense. If your project is not going to be maintained for years, please feel free to skip paradigms. Use spaghetti architecture. Use mixed javascript, php, perl and have fun with testing on production. Building a prototype is a kind of development. Write once and dispose the code soon. But in project that is planned for more than three months this approach is just as wrong like murdering your client with an axe and taking their money. Just like Vikings did.

Wikingowie (Wolin 2018 04)

It is all about maintainability. If you use dynamic typing but do not cover your app with test, expect your work will get broken by colleagues siting next to you and following your discipline. If you do not use interfaces - I expect I know already how your tests look like. Like `null`. If you prefer not to extract method I know how lightweight your code is. I have seen java class source code that had over 1 megabyte! Imagine how fast you can deliver business value in such a project. If you think design is a waste - yeah... I was there, I have seen important application presenting different results on each subpage, thanks to `if` pyramid of doom, copied, pasted and happily living its own life. It does cost. Believe me. Technical debt is not something that will disappear by just forgetting the matter.

Elegant Objects by Yegor Bugayenko gives you some kind of framework. By following author's 23 pieces of advice you can learn how to use Object Oriented Paradigm in real language like Java. Yegor conducts personalized object (Mr. Object) through journey of life. The very similar way as we personalize actors using eg. Akka and follow some important rules - not forced by language itself. This concept seems to be core of author's approach to improve maintainability of software we create. When we interact with a person, we stick to some polite way of communication, assuming we are not talking to an idiot. Same holds for our objects.

There are some other helpful tricks and lot of strong opinions on using some code constructs and patterns/antipatterns. The book gives number of easy to remember code examples. Explains or recall you why constructor injection is the only right way and why `static` is not welcomed (even if we do now FP in Java). If you are more interested in the content of the book - I can recommend Tomek's review and page of Yegor Bugayenko.

Some of author's rules I think may be a bit controversial and exaggerated - at least in context of my last project. The only point I really didn't like was actually Yegor's approach to C++, a bit unfair as this language can be as object oriented as Java is.

I am not imposing that there is only one way to create maintainable software. Whether you will use header files to separate contract from implementation or will you use java interfaces or maybe free monads that define program separated from its interpretation. It is up to you. But please, take some set of rules, and keep to them in consistent manner. That is what your client pays you for.