Blog: Latest Entries (15):


i don't like Release-Branches

Ich halte Release-Branches für sehr problematisch. Manchmal können sie nützlich sein, aber in 99% aller Fälle sind sie überflüssig und bringen mehr Probleme mit sich. Nur wenn wirklich mehrere von einander abhängige Features gleichzeitig entwickelt werden wäre ein Release-Branch denkbar. Ob der dann auch wirklich einen Vorteil bringt, muss jeder dann für sich entscheiden.

Das Problem bei Release-Branches ist, dass alles was release-bereit ist auch da rein kommt. Schnell hat man das Problem, dass man seinen kleinen Fix da rein merged und feststellt, dass 3 weitere Features da drin liegen. Sie sind ja release-bereit, aber ein Release war noch nicht wirklich nötig. Entweder ändern die was, wo man die Benutzer noch instruieren muss oder sie sind nicht so wichtig man hat den Release auf den Ende des Sprints geschoben. Jetzt steht man da und muss erst mal von allen anderen die Info einholen, ob man die Features mit seinem Fix mit releasen kann oder man jetzt doch einen eigenen
Release-Branch aufmachen sollte.


Bloß weil etwas release-fertig ist, heißt es nicht dass ein Release möglich ist!


Die meisten Features und Fixes stehen für sich selbst und sie in einen gemeinsamen Release-Branch zu bringen blockiert schnelle Releases einzelner Features. Für jeden Feature-Branch einen eigenen Release-Branch auf zu machen ist aber auch nicht sinnvoll. Der Feature-Branch sollte meiner Meinung nach auch sein eigener Release-Branch sein... also man braucht nur den Feature-Branch.

FALSCH:
bbcode-image
blocking release-branch.. nicht gut


RICHTIG:
bbcode-image


Dieser Post fußt auf meinen Post Git State Konzept.

Summernote: Image Resizing

Das direkte Einbinden als Base64 Data-URL ist echt praktisch, aber man will ja nicht, dass die Benutzer nun endlos riesige Bilder darüber einbinden. Deswegen ist es eine gute Idee, die Bilder beim Einfügen auch gleich zu verkleinern. Das ist zum Glück mit dem Canvas-Element sehr einfach.

Die Callback-Function:

let onImageUploadFunc = function (elementId) {
return function(image) {
resizeImage(image[0], elementId);
}
};

function resizeImage(file, elementId) {
let image = new Image();
let url = window.URL ? window.URL : window.webkitURL;

image.src = url.createObjectURL(file);
image.onload = function (e) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");

let width = 600;
let factor = image.width / width;
let height = image.height / factor;

if(image.height > image.width) {
height = 300;
factor = image.height / height;
width = image.width / factor;
}

canvas.width = width;
canvas.height = height;

ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
$(elementId).summernote('editor.insertImage', canvas.toDataURL('jpeg', 0.7));
};
}


Verwendung:

$('#editSolution').summernote(
{callbacks:{onImageUpload: onImageUploadFunc('#editSolution')}}
);


bbcode-image

Release-unrelevante Änderungen direkt in den Master?

Nur ein kleiner Fix an der README.md oder ein Kommentar in der docker-compose.yml? Braucht es einen feature-Branch? An sich sind solche Änderungen es ja nicht wert die Versionsnummer zu erhöhen, weil sich am releasten Code ja nichts ändert. Aber das einfach so in den Master commiten, obwohl darin nur Abbildungen von release-Tags als Commits zu finden sollten (nach dem ersten Release)?

Das Release als lauffähiges Artefakt eines Dev-Standes würde sagen: Ja, es sollte wie eine Code-Änderung behandelt werden. Eine Version bezieht sich nicht nur auf das fertige Artefakt sondern auf auf dessen Sources aus denen das Artefakt erstellt wurde. Eine falsche Angabe in der README.md ist genau so ein Fehler wie ein Fehler im Code und könnte später zu Missverständnissen und nicht lauffähigen Artefakten führen.

bbcode-image



Also jeder Fix und jede Verbesserung soll einen eigenen Branch und einen Release-Tag erhalten.


Meine Erfahrungen aus Shopware-Plugin Zeiten sagt dann eher, dass man nicht jeden Release auch wirklich releasen muss. Wenn 0.3.2 im Vergleich zu 0.3.1 keine Verbesserung für den Enduser bringt, muss kein öffentlicher/public Release erfolgen sondern es bleibt ein privater Release, der für die Developers gedacht ist.

Docker: Test SSH-Server

Manchmal muss man z.B. das Kopieren von Dateien auf einen Server per SCP testen. Oder auch einfache Deployments auf einem Server. Hier ist ein kleines SSH-Server Image mit Bash und Rsync.


FROM sickp/alpine-sshd:7.5
RUN apk update
RUN apk add bash
RUN apk add rsync


Und in einer docker-compose.yml

version: "3.0"

services:
ssh-server:
build: .
ports:
- "2222:22"


User: root
Password: root

Man kann aber auch authorized-keys hinterlegen, wie auf der Seite des Base-Images erklärt wird.

Ist es ok mit einem dreckigen Master zu starten?

Ist es okay mit einem dreckigen Master-Branch zu starten?


Meiner Meinung nach ist es vollkommen ok. Ein leeres Projekt als stable zu deklarieren macht keinen Sinn und ist in den meisten Fällen auch nicht deploybar, da z.B. eine build.xml oder .gitlab-ci.yml noch fehlen.

bbcode-image
Master mit dirty Commit vor dem ersten Release


Ich vertrete die Meinung, dass der Master erst nach dem ersten Release stable gehalten werden muss. Es folgt der Regel, dass im Master der letzte nutzbare Stand liegt. Wenn kein Release vorhanden ist, ist der letzte Commit der Dev-Version, die nutzbarste Version die man finden kann. In dem Sinne bemühe ich bei der Regel eine Art Fallback auf die Dev-Version, für die Zeit wo kein Release existiert. Nach dem ersten Release ist immer das letzte Release die nutzbarste Version.

Es gibt also immer eine nutzbare Version und nie "Nichts".

Dieser Post fußt auf meinen Post Git State Konzept.

WSL und Vue Probleme

Wenn ich in Ubuntu unter meinem Windows 10 Node.js und NPM installiere macht es nur Probleme. "npm install" beschwert sich dass 'in' unbekannt sei.

Momentan läuft es bei mir so am Besten:


curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get update && sudo apt-get install -y nodejs


Dann funktioniert auch die Vue-CLI Installation:


npm install -g @vue/cli
npm install -g @vue/cli-service-global


Unter Windows direkt... da war alles noch schlimmer.

CoreUI mit JSON-Schema

Eine Admin-UI lebt nicht nur von Tables sondern auch von sehr vielen Forms. Die möchte man ja nur ungern komplett per Hand bauen sondern etwas wie JSON-Schema benutzen, da man das auch auf Server-Seite für die Validierung nutzen kann.

CoreUI und vue-form-generator arbeiten gut zusammen.

Man muss vue-form-generator nur per NPM installieren.

bbcode-image



<template>
<CRow>
<CCol col="12" md="6">
<CCard>
<CCardHeader>
JSON-Schema Form
</CCardHeader>
<CCardBody>
<vue-form-generator :schema="schema" :model="model" :options="formOptions">
</vue-form-generator>
</CCardBody>
<CCardFooter>
<CButton block color="primary">Submit</CButton>
</CCardFooter>
</CCard>
</CCol>
</CRow>
</template>

<script>
import Vue from 'vue'
import VueFormGenerator from 'vue-form-generator'

Vue.use(VueFormGenerator);

export default {
name: 'Alerts2',
data () {
return {
model: {
id: 1,
name: 'John Doe',
password: 'J0hnD03!x4',
skills: ['Javascript', 'VueJS'],
email: 'john.doe@gmail.com',
status: true
},
schema: {
fields: [
{
type: 'input',
inputType: 'text',
label: 'ID (disabled text field)',
model: 'id',
readonly: true,
disabled: true
},
{
type: 'input',
inputType: 'text',
label: 'Name',
model: 'name',
placeholder: 'Your name',
featured: true,
required: true
},
{
type: 'input',
inputType: 'password',
label: 'Password',
model: 'password',
min: 6,
required: true,
hint: 'Minimum 6 characters',
validator: VueFormGenerator.validators.string
},
{
type: 'select',
label: 'Skills',
model: 'skills',
values: ['Javascript', 'VueJS', 'CSS3', 'HTML5']
},
{
type: 'input',
inputType: 'email',
label: 'E-mail',
model: 'email',
placeholder: 'User's e-mail address'
},
{
type: 'checkbox',
label: 'Status',
model: 'status',
default: true
}
]
},
formOptions: {
validateAfterLoad: true,
validateAfterChanged: true,
validateAsync: true
}
}
}
}
</script>


Ja das ist einfach das Beispiel, das ich kopiert habe.... aber es funktioniert!

bbcode-image

CoreUI: Ein Admin-Template für Vue

Schon als ich mit React arbeiten musste, war ich sehr von den vorgefertigten Admin-Templates angetan. Jetzt darf ich auch mal damit rumspielen und meine ersten Erfahrungen damit sind schon relativ positiv. Da ich mit meinem Job synchron bleiben wollte habe ich mit CoreUI angefangen.

Die Installation über GitHub ist einfach und schnell.

Um ein eigens View anzulegen muss man an sich drei Dinge tun.

1. Die View anlegen:

bbcode-image


bbcode-image


2. In router/index.js die Component importieren und in die Router-Config einfügen:

bbcode-image

bbcode-image


3. In containers/_nav.js einen Link für die Sidebar einfügen:

bbcode-image


4. Dann den Server starten:

npm run serve


Und unter http://localhost:8080 angucken.

bbcode-image


Geht an sich alles ganz einfach.

Git State Konzept

Am Freitag hat mir mein Kollege 2 Links zu Blogposts geschickt, die sich mit der Frage beschäftigen ob Git-Flow in der heutigen Zeit überhaupt noch funktioniert oder ob Git-Flow veraltet ist. Der 1. Blogpost zeigt erstmal nur Probleme auf und enthält keine Lösungen. Es passiert zu leicht das Release-Branches zu lange leben und dann darin selbst Entwicklung geschieht. Es dauert relativ lange bis eine Änderung durch die verschiedenen Branches im Master ankommen und am Schlimmsten ist noch, dass bei parallelen Entwicklungen ein nicht releaster Branch einen anderen aktuelleren, der einfach schneller war, blockiert.

Ja. Das ist jetzt nicht neu. Über diese Probleme habe ich 2009 schon im dem damaligen ERP-Team diskutiert (mein Gott waren wir damals schon modern...). Die Lösung hier ist einfach dass man harte Feature- und Code-Freezes braucht. Auch darf die Fachabteilung nicht erst im Release-Branch das erste Mal die neuen Features sehen. Ich habe es so erlebt. Dann kamen die neuen Anforderungen, Änderungen der gerade erst implementierten Features. Das soll aber so sein. Wenn das so ist braucht man aber auch noch das. Das ist falsch und muss so funktionieren... Alles Dinge die schon viel früher hätten klar sein müssen und erst dann hätte es zu einem Release-Branch kommen dürfen. Der Stand eines Feature-Branchs muss genau so auf einem System für Test und Abnahmen deploybar sein wie ein Release-Branch. Anders gesagt jeder Stand muss einfach immer präsentierbar sein!

Der 2. Blogpost brachte jetzt auch nicht wirklich neue Erkenntnisse, was am Ende der Author auch selbst schreibt.

Ich halte die Darstellung von Branches in parallelen Slots oder Lanes, die in dem Sinne ein Rennen um die Aktualität austragen für vollkommen falsch. Es darf auch nicht den develop-Branch oder den einen Release-Branch geben, der auch dann immer deckungsgleich mit dem Stand des Deployments auf einem System ist. In Zeiten von Docker und Reverse-Proxies zusammen mit Wildcard-Subdomains sind feste Systeme sowie so überholt. Jeder Branch kann ein System haben, auf dem Test, Abnahmen und Dokumentation stattfinden kann.
Das gilt auch für Tags. Branches sind variabel und ändern sich immer wieder. Tags sind statisch und damit perfekt für Zwecke, wo man kontrolliert bestimmte Stände deployen möchte. Tags persitieren einen bestimmten State/Zustand des gesamten Git-Repositories. Branches bilden einen State/Zustand aus der Sicht eines bestimmten Entwicklers oder eines bestimmten Features ab.

Deswegen halte ich feste Branches wie mit festen Aufgaben für komplett falsch. Ein Feature = ein Branch und am Ende steht ein Tag, der den gewünschten State/Zustand persitiert.

Ein einfacher Feature Branch:
bbcode-image


Ja es gibt noch einen Master-Branch, der aber in dem Sinne nur ein 2D Abbild des wilden mehr dimensionallen Feature Raum ist. Wenn wir jeden Feature-Branch als Vektor der auf das einzelne Feature/Tag als Ziel zeigt versteht, ist der Master einfach die Projektion aller Vektoren auf eine Fläche. Diese vereinfachte Projektion hilft Feature-Branches vor dem Release auf den aktuellen Stand (was andere Features und Fixes angeht) zu bringen.

Es gibt auch immer mal Abstimmungsprobleme bei Features, die auf einander aufbauen. Interfaces haben minimale Abweichungen oder ein kleiner Satz in der Dokumentation wurde falsch verstanden. Was also wenn ein Feature doch noch eine kleine Änderung braucht, weil Entwicklungen parallel liefen?

Beides wird gleichzeitig fertig (ein extra Release-Branch wäre möglich):
bbcode-image


Das Basis-Feature geht vorher live:
bbcode-image
Das bessere und flexiblere Vorgehen


Gibt es einen Unterschied zwischen Fixes und Features? Nein. Beides sind Improvements des aktuellen States/Zustands. Wenn einem in einem Feature-Branch ein allgemeines Problem auffällt, fixt man das Problem und merged den Master mit der neuen Version erneut in den Feature-Branch.

Zwischenzeitlicher Fix:
bbcode-image


Es ist an sich kein Unterschied zwischen einem Fix und einen weiteren Feature-Branch, außer dass der Fix-Branch sehr viel kurzlebiger ist und wohl weniger Commits enthält.

Der Master ist immer stable, weil nur Release-Tags darauf abgebildet sind.

Dieses Herangehen macht es sehr einfach jeden State/Zustand auf System abzubilden. Jeder Branch ist unter seinem Namen zu finden und Tags werden nach Typ auf Systeme gemappt.

Tag auf System:
- release-XXX auf das produktive System
- staging auf das Staging-System (1:1 Namenabbildung)
- demo1-n auch 1:1 per Namen abbilden

Bei staging muss man den Tag löschen und neu anlegen, so kann jeder Zustand auf dem Staging-System deployt werden oder besser gesagt, wird ein Deployment durchgeführt das dann unter der Staging-Domain erreichbar ist. Hier gibt es eine tolle Anleitung wie man solche Systeme mit Traefik oder Kubernetes ganz einfach bauen kann. Ich werde das aber vielleicht auch noch mal genauer beschreiben, wie ich es für gut halte.

Denn Branches halte ich persönlich es nicht für wert wo anders als lokal in einem Docker-Container zu laufen. Da kann ich um es der Fachabteilung lieber schnell einen Tag erstellen und diesen nach dem Input der Abteilung auch wieder unter selben Namen neu anlegen oder unter einen neuen wenn zwei mögliche Umsetzungen verglichen werden sollen (macht das mal mit Git-Flow!).

Edit: Ich habe die per Hand gezeichneten Diagramme durch vollständigere Diagramme, die per Software erstellt wurden, ausgetauscht.

Home Office

Arbeiten und nebenbei Folding At Home auf der Workstation laufen lassen.

MS Teams läuft wirklich nicht immer ganz so rund. Aber im Gegensatz zu den Berichten vieler anderer habe ich mit meiner kleinen 1Gbit Kabel Internetleitung und VPN keine Probleme. Also alles super so weit.

bbcode-image

Lenovo IdeaPad z570 und Win10

Bis jetzt hatte ich nie Probleme Windows 10 auf einem PC oder Notebook zu installieren, dass ursprünglich mit Vista, Win7 oder Win8 lief. Aber es gibt immer ein erstes mal. Hier bei handelte es sich um ein Lenovo IdeaPad z570, das ungefähr Jahrgang 2011/2012 ist. Es ist also noch gar nicht so alt. Ein Lenovo T61 aus dem Jahr 2007 und zwei T500 aus dem Jahr 2008 hatten keine Probleme mit Windows 10. Das z570 hatte auch nur ein Problem mit Windows 10: Es ging nicht aus. Auch bei einem Neustart fuhr es zwar runter, aber verblieb dann in einem undefinierten Zustand in dem die LEDs der Zusatztasten und des Power-Switch weiter leuchteten und der Lüfter voll aufdrehte.
Schon bei der Installation musste ich beim ersten Neustart das Notebook per Hand ausschalten. Als Windows 10 dann installiert war führte es dazu, dass sich das WLAN danach ausgeschaltet hatte und nicht wieder einzuschalten war. Windows verwies immer auf den Schalter am Gehäuse, aber der war eingeschaltet. Als erstes befürchtete ich, dass ich ein BIOS-Update machen müsste, aber nach vielen Herumprobieren und Versuchen, wich der Vermutung eine klare Sicherheit, dass es so sein musste.
Also BIOS-Update herunter geladen, gestartet und direkt in einen Bluescreen gelaufen. Selbst mit Adminrechten kam wieder der Bluescreen.
Zum Glück hatte ich die Festplatte mit Windows 7 noch daneben liegen (das mich auch direkt beim letzten Herunter fahren mit ein paar Updates beglückt hatte). Also die Festplatte wieder eingebaut.

bbcode-image


bbcode-image


Da merkte man erst mal wie schnell doch die neue SSD war, auch wenn es die billigste SSD war, die ich bei Amazon gefunden hatte. Windows bootete wieder und das Programm für das BIOS-Update lief sofort einmal sauber und schnell durch.

bbcode-image


Dann wieder Festplatte gegen die SSD getauscht. Windows 10 gestartet und wieder herunter gefahren. Die Lichter leuchteten, leuchteten und gingen dann doch aus. Der Lüfter stoppte.

Fazit: Immer Windows 7 für Notfälle weiter vorhalten und vielleicht mal ein BIOS-Update einplanen.

Das z570 war aber auch sonst schon leicht mitgenommen. Das Gehäuse des Lüfters war so eingedrückt, dass der Lüfter fest saß und alles extrem heiß wurde. Mit etwas Gewalt und biegen, war der Lüfter wieder frei zu bekommen und lief sogar direkt wieder. Ich war mir nicht sicher gewesen, dass er nicht doch dadurch kaputt gegangen war.

bbcode-image


Da ich ihn ja sowie so ausbauen musste, wurde auch gleich die total
eingetrocknete Wärmeleitpaste für CPU und GPU ersetzt und auch der Chipsatz bekam welche ab. Der hatte zwar eine Verbindung zum Kühlkörper der CPU aber selbst keine Wärmeleitpaste.

Noch die 2x 2GB gegen ein 8GB Modul ausgetauscht und alles lief so schnell, dass das Notebook sicher noch 3-4 Jahre ohne Probleme seine Aufgaben erledigen kann.

Mini-USB Kamera brauchbar machen

Kleine USB-Kameras sind sehr praktisch, wenn man mit ihnen 3D-Drucke überwachen, Bilderkennung oder auch kleine IoT-Projekte mit QR-Code Scans realisieren will.

bbcode-image


Ich hatte mir eine sehr kleine Kamera aus China bestellt, war aber mit der Bildqualität nie wirklich zufrieden. Das Bild war immer unscharf und Lichter bildeten immer unschöne Ränder um alles.

bbcode-image


Am Ende habe ich mir jetzt das Objektiv genauer angesehen und den IR-Filter endeckt, der einfach als kleine Plättchen hinten rauf geklebt war. Mit Hilfe eines feinen Schraubenziehers und viel Gewalt gelang es mir den IR-Filter zu entfernen/weg zu brechen.

bbcode-image


Nun ist zwar mein graue Jacke etwas lila, aber das Bild ist sehr scharf und und hell. mit einen IR720 Filter kann bestimmt gute Aufnahmen im IR-Bereich machen und bei Kunstlicht sind die leichten Verfärbungen sowie so kein Problem mehr.

PHP Tests mit Code-Coverage

Wenn man Code-Coverage bei Unittests mit PHP haben will benötigt man extra Erweiterungen, wie z.B. XDebug. XDebug ist aber sehr langsam und deswegen gibt es Alternativen wie PCOV. Wenn man das nun installieren will kann es zu Problemen bei "docker-php-ext-install" auf den offiziellen PHP-Docker-Images kommen. Um es dort zu installieren, muss man


pecl install pcov && docker-php-ext-enable pcov


ausführen. Dann funktioniert die Installation und es steht für Unit-Tests zur Verfügung.



Older posts:

Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?