Cloud Build & FirstSpirit Dev Tools

Veröffentlicht am 06.04.2020

Bezugnehmend auf unseren Blogbeitrag “Agile Entwicklung mit FirstSpirit: External Sync” wollen wir einen kurzen Einblick geben, wie eine automatische Aktualisierung der Firstspirit-Projekte mit Google Cloud Build funktioniert.

Research and Development

Ausgangssituation

Auch Automatisierung hat viele Ausbaustufen. Hier betrachten wir ein Unternehmen, das früher einen zentralen FirstSpirit-Server hatte und die Entwickler haben ihre Templates auf lokalen Firstspirit-Servern gebaut. Eine Aktualisierung der Templates im QA- bzw. Produktiv-Projekt erfolgte zunächst über Pakete mit Content-Transport. In der nächsten Entwicklungsstufe erfolgte dann die Aktualisierung der Templates über die FirstSpirit Dev Tools.

Zielsetzung

Im angedachten Zielstand möchte man die manuellen Schritte bei einem Templateupdate wegautomatisieren. Sobald ein Entwickler Templateänderungen in das zentrale Code-Repository eincheckt, soll automatisch eine Aktualisierung im richtigen Projekt FS-Projekts erfolgen. Commits z.B. zum master-branch sollen automisch im QA-Projekt landen.Die Aktualisierung des Produktiv-Projekts soll zwar ähnlich vorbereitet sein, aber immer noch einen (einzelnen) manuellen Trigger aus Sicherheitsgründen voraussetzen.

Vorgehen

Da die einzelnen Schritte im Google Cloud Build über die sogenannten "cloud-builders" (vorkonfektionierte Container) ausgeführt werden, versuchen wir nach Möglichkeit diese zu verwenden. Dies erspart es uns eigene Container zu erzeugen.

Als Erstes haben wir in unserem Projekt eine "pom.xml" angelegt, um über Maven die Firstspirit Dev Tools aufzurufen.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>de.aboutcontent.blogpost</groupId>
	<artifactId>website-project</artifactId>
	<version>0.0.1</version>
</project>

Im nächsten Schritt erweitern wir unsere "pom.xml" um ein Profil, mit dessen Hilfe wir die Templates per "External Sync" in unser Ziel-Projekt transportieren können.

<profile>
	<id>import</id>
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.6.0</version>
				<executions>
					<execution>
						<goals>
							<goal>exec</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<longModulepath>false</longModulepath>
					<executable>bin/fs-cli.sh</executable>
					<arguments>
						<argument>-u</argument>
						<argument>${firstspirit.user}</argument>
						<argument>-pwd</argument>
						<argument>${firstspirit.pass}</argument>
						<argument>-h</argument>
						<argument>${firstspirit.host}</argument>
						<argument>-port</argument>
						<argument>${firstspirit.port}</argument>
						<argument>-c</argument>
						<argument>${firstspirit.mode}</argument>
						<argument>-p</argument>
						<argument>${firstspirit.project}</argument>
						<argument>-sd</argument>
						<argument>src</argument>
						<argument>import</argument>
					</arguments>
				</configuration>
			</plugin>
		</plugins>
	</build>
</profile>

Damit über die "pom.xml" keine Zugangsdaten im Repository abgelegt werden müssen UND wir die Möglichkeit haben die Templates in unterschiedliche Projekte auf unterschiedlichen FirstSpirit Servern zu installieren, werden die meisten Argumente als Properties in eigenen Profilen in der "settings.xml" definiert. Das Profil für einen lokalen FirstSpirit Server sieht dann beispielsweise wie folgt aus:

<profile>
	<id>firstspirit-localhost</id>
	<properties>
		<firstspirit.host>localhost</firstspirit.host>
		<firstspirit.port>8000</firstspirit.port>
		<firstspirit.mode>HTTP</firstspirit.mode>
		<firstspirit.user>Admin</firstspirit.user>
		<firstspirit.pass>Admin</firstspirit.pass>
		<firstspirit.project>Demoprojekt</firstspirit.project>
	</properties>
</profile>

Um das Ganze ausprobieren zu können, müssen wir als nächstes eine entsprechende Ordnerstruktur erzeugen, in der wir die benötigten Dateien ablegen.

Unser Projekt-Verzeichnis sollte hinterher in etwa wie folgt aussehen:

.
├── bin
│   ├── fs-cli.cmd
│   └── fs-cli.sh
├── conf
│   └── log4j.properties
├── lib
│   ├── fs-access.jar
│   └── fsdevtools-cli-2.5.6.jar
├── pom.xml
└── src

Nun sind wir in der Lage den Import-Vorgang mit unserem lokalen FirstSpirit-Server zu testen. Hierzu führen wir einfach den folgenden Befehl in der Shell-Console aus:

mvn exec:exec -Pfirstspirit-localhost -Pimport

Als Nächstes müssen wir die “fs-access.jar” über Maven herunterladen. Hierzu legen wir uns ein weiteres Profil in der "pom.xml" an, indem wir das gleiche Maven-Plugin wie zuvor nutzen.

<profile>
	<id>get-fs-access-jar</id>
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.6.0</version>
				<executions>
					<execution>
						<goals>
							<goal>exec</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<longModulepath>false</longModulepath>
					<executable>wget</executable>
					<arguments>
						<argument>--user</argument>
						<argument>${artifactory.user}</argument>
						<argument>--password</argument>
						<argument>${artifactory.pass}</argument>
						<argument>http://artifactory/de/espirit/firstspirit/fs-access/${firstspirit.version}/fs-access-${firstspirit.version}.jar</argument>
						<argument>-O</argument>
						<argument>lib/fs-access.jar</argument>
					</arguments>
				</configuration>
			</plugin>
		</plugins>
	</build>
</profile>

Wenn wir nun also vor dem Aufruf des eigentlichen Import-Vorgangs den folgenden Befehl in der Console ausführen, wird uns für das entsprechende Zielsystem die passende "fs-access.jar" im Lib-Verzeichnis abgelegt.

mvn exec:exec -Pfirstspirit-localhost -Pget-fs-access-jar

Damit hätten wir dann das erste Teilziel erreicht, indem wir nun in der Lage sind die FirstSpirit Dev Tools über Maven auszuführen.

Google Cloud Buckets und Build

Im nächsten Schritt müssen wir alle Dateien, die wir nicht im Repository ablegen wollen, in ein Bucket im Google Cloud Storage desselben Cloud-Projekts ablegen. In unserem Beispiel legen wir uns in dem Bucket zwei Ordner an. Im Ordner “ci-maven” legen wir unsere "settings.xml" ab und in den Ordner “fs-cli” kopieren wir alle Dateien des FirstSpirit Dev Tools.

Als Nächstes müssen wir definieren, was Google Cloud Build beim Ausführen des Triggers machen soll. Die einzelnen Schritte werden in der Datei “cloudbuild.yaml” definiert, die ebenfalls im Source-Repository abgelegt werden muss, damit der Trigger zum Ausführungszeitpunkt darauf zugreifen kann.

Da wir beim Buildvorgang keine Container erzeugen, haben wir in der Datei nur den Bereich “steps”. Daher lassen wir Cloud Build die Dateien kopieren, die nicht im Source-Repository liegen, aber für den Build-Vorgang benötigt werden.

  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/fs-cli/bin/fs-cli.sh', 'bin/fs-cli.sh']
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/fs-cli/lib/fsdevtools-cli-2.5.6.jar', 'lib/fsdevtools-cli-2.5.6.jar']
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/fs-cli/conf/log4j.properties', 'conf/log4j.properties']
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/ci-maven/settings.xml', 'settings.xml']

Nach dem Kopieren führen wir den ersten Maven-Schritt aus, indem die benötigte “fs-access.jar” aus unserem Artifactory heruntergeladen wird.

  - name: 'gcr.io/cloud-builders/mvn'
    args: ['--settings', '/workspace/settings.xml', 'exec:exec', '-Pget-fs-access-jar', '-Pfirstspirit-prod']

Nachdem nun alle benötigten Dateien in unserem Cloud Build Workspace vorhanden sind, müssen wir die Datei “bin/fs-cli.sh” ausführbar machen. Hierzu bedienen wir uns eines vorgefertigten Ubuntu Containers.

  - name: 'ubuntu'
    args: ['chmod', '755', '/workspace/bin/fs-cli.sh']

Nun können wir den letzten Schritt angehen, durch den die eigentliche Aktualisierung des Projekts vorgenommen wird. Hierbei geben wir anstelle des Profilnamens für unser Zielprojekt die Variable "${_PROJECT_PROFILE}" an, die zur Laufzeit vom Trigger ersetzt wird.

Unsere finale “cloudbuild.yaml” Datei sollte nun in etwa so aussehen:

steps:
  # copy fs-cli
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/fs-cli/bin/fs-cli.sh', 'bin/fs-cli.sh']
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/fs-cli/lib/fsdevtools-cli-2.5.6.jar', 'lib/fsdevtools-cli-2.5.6.jar']
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/fs-cli/conf/log4j.properties', 'conf/log4j.properties']
  - name: gcr.io/cloud-builders/gsutil
    args: ['cp', 'gs://artifacts.ac-shout.appspot.com/ci-maven/settings.xml', 'settings.xml']
  # get fs-access.jar
  - name: 'gcr.io/cloud-builders/mvn'
    args: ['--settings', '/workspace/settings.xml', 'exec:exec', '-Pget-fs-access-jar', '-Pfirstspirit-prod']
  # make fs-cli executable
  - name: 'ubuntu'
    args: ['chmod', '755', '/workspace/bin/fs-cli.sh']
  # import to firstspirit
  - name: 'gcr.io/cloud-builders/mvn'
    args: ['--settings', '/workspace/settings.xml', 'exec:exec', '-Pimport', '-P${_PROJECT_PROFILE}']

Nach dem Übertragen aller angelegten bzw. geänderten Dateien in das Source-Repository können wir nun den eigentlichen Trigger anlegen. Hierbei gehen wir nur auf die für unseren Fall wichtigen Einstellungen ein.

Google Cloud Build - Trigger EInstellungen
Google Cloud Build

Für das Triggerereignis haben wir verschiedene Möglichkeitn: Wir können wie o.g. bei einem commit zu einem Branch das FirstSpirit projekt aktualisieren, z.B., Push auf "dev-branch" ergibt ein update auf dem zentralen DevServer. Eine andere Variante wäre es auf bestimmte Tags zu reagieren und nur genau diese zu aktualisieren. Hier haben wir auch die Möglichkeit über RegEx Flexibilität zu bekommen, z.B. ein neuer Tag beginnend mit "RELEASE_CANDIDATE" wird auf dem QA Server geschoben.

Im Bereich “Build-Konfiguration” geben wir an, welche Datei in unserem Source-Repository die Konfiguration der einzelnen Schritte beinhaltet.

Zum Abschluss müssen wir noch die Substitutionsvariable "_PROJECT_PROFILE" anlegen und ihr den Profil-Namen für das entsprechende Zielprojekt zuweisen.

Für unser QA-Projekt wird der Trigger automatisch ausgelöst. Bei unserem Produktiv-Projekt würde der Trigger hingegen manuell ausgeführt werden.

Fazit

In diesem Beitrag haben wir gezeigt wie man Google Cloud Build nutzen kann, um verschiedene Entwicklungsstände automatisch und komfortabel auf den FirstSpirit Server aktuell zu halten. Wir haben so eine Grundlage geschaffen eine Zielumgebung zu haben, die immer die aktuellesten Inhalte zu einem Projekt hat. Im Anschluss an die erfolgreiche Ausführung der Triggers könnten wir so nun automatisiert Ende-zu-Ende-Tests laufen lassen, um das Zusammenspiel des Projektes mit anderen Komponenten der Entwicklung zu testen.

facebook icon twitter icon xing icon linkedin icon
© 2020 aboutcontent GmbH