Skip to content

Instantly share code, notes, and snippets.

@smichaelsen
Last active August 12, 2022 14:11
Show Gist options
  • Save smichaelsen/4abf5e280f5700f4acdc8062f04767b4 to your computer and use it in GitHub Desktop.
Save smichaelsen/4abf5e280f5700f4acdc8062f04767b4 to your computer and use it in GitHub Desktop.
Setting up a Build Server for TYPO3 projects on Gitlab.com

Setting up a Build Server for TYPO3 projects on Gitlab.com

Background

We're a small team of only two people, but we're tackling more and more rather big TYPO3 projects. Over time we introduced package management for PHP (composer) and JS (bower) and depended on frontend building with Grunt. With rising complexity and importance of our projects we felt the demand for an efficient and safe way to deploy our websites on different servers.

We helped our selves with small self written deploy scripts that performed building on the target server, but you can't run node (for Grunt) or sass in every environment, and if building goes wrong the website was likely to be broken on the live server - so we needed a Build Server.

But solutions we looked at turned out to be quite time consuming (setting up and managing self hosted Gitlab and Gitlab-CI or a Jenkins server and runners) or costly.

Free Hosting on Gitlab.com

Since a few months Gitlab.com offers free hosting for private repositories and also a free "shared" build runner. I really like the Gitlab interface and its features, but I also need to tell you the downside of building everything on Gitlab.com hosted repositories:

Since they started their free service, the git server was always a bit slow and they promised to improve speed. I didn't notice any improvements so far. So any network based git operations (pull, push, fetch, etc) take a few seconds to complete. Something that we accept for the benefits we get.

Set up

To enable the building for a repository you need to provide a .gitlab-ci.yml file on the root level of your project.

We organize our TYPO3 installations by having a main repository for the installation and more repositories for each of our client specific TYPO3 extensions. We load all extensions via composer. Most of our extensions need some frontend building to run properly. What we want our Build Server to do is:

  • Load the main repository
  • Load the composer dependencies
  • Perform frontend building for our custom extensions
  • Sync the ready-to-run installation on the target server
  • Perform finishing commands on the target server (like clearing the cache, making a backup, perform database scheme compare etc)
  • Notify us if something goes wrong

Here's what a .gitlab-ci.yml looks like for a project of ours:

variables:
  SSH_HOST: username@ssh.targethost.org
  SSH_PATH: html

stages:
  - deploy
  - notify

deploy:
  stage: deploy
  before_script:
    - apt-get update -qq && apt-get -qq install -y nodejs npm php5 php5-cli ruby rsync
    - ln -s /usr/bin/nodejs /usr/bin/node
    - gem install sass
    - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
    # we include a .ssh folder in our project with a keypair to authenticate ourselves on the target server. Further down the folder is excluded from the rsync command. That's important - you MUST NOT have your keys be downloadable on the webserver
    - mkdir ~/.ssh && cp .ssh/id_rsa ~/.ssh/ && chmod 600 ~/.ssh/id_rsa && cp .ssh/id_rsa.pub ~/.ssh/ && cp .ssh/config ~/.ssh/
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
  script:
    - composer install --no-dev
    - cd typo3conf/ext/client_extension_1
    - npm install && ./node_modules/grunt-cli/bin/grunt build
    - cd - && cd typo3conf/ext/client_extension_2
    - npm install && ./node_modules/grunt-cli/bin/grunt build
    - cd -
    - rsync -az -e "ssh" --delete --exclude=fileadmin --exclude=typo3conf/l10n --exclude=.git --exclude=node_modules --exclude=bower_components --exclude=typo3temp --exclude=.ssh --exclude=.sass-cache --exclude=/uploads ./ $SSH_HOST:$SSH_PATH/
    # Perform some commands on the target server as you need
    - ssh $SSH_HOST 'cp $SSH_PATH/typo3conf/AdditionalConfiguration_Stage.php $SSH_PATH/typo3conf/AdditionalConfiguration.php && cd $SSH_PATH && ./scripts/backup_on_deploy.sh'

notify_build_error:
    stage: notify
    when: on_failure
    script:
        - curl --data "Deployment failed // Build error! $CI_BUILD_REF $CI_BUILD_REPO" $'https://our-slack-team.slack.com/services/hooks/slackbot?token=someslacktoken&channel=%23general'

Running a build with this setup takes something between 4 and 7 minutes. It is triggered on every commit. Next steps would be to distinguish between staging and production server (e.g. by branch).

The yml file has a lot more options: http://doc.gitlab.com/ee/ci/yaml/README.html

Performing tests

Our build process does not execute any tests on the extensions. They don't belong here. Performing tests on the extensions should be done by adding a build job to their repositories so you get aware of problems while comitting extension changes.

What could be added here are functional tests for the website. But at this stage we have none.

Conclusion

This is what we have so far. We're new to the topic and happy about any feedback or input. Also I hope to help to get more people started.

Sebastian Michaelsen
@s_michaelsen
sebastian@app-zap.de
http://app-zap.de

@Bufallo
Copy link

Bufallo commented May 3, 2016

Hi Sebastian!

As you are already using node/npm i would recommend you to take a look at shipit.

I use that in my projects for deployment.
It follows the same principle like capistrano or TYPO3.Surf.
You are deploying to a fresh folder and when everything is finished, just a symlink is changed.
So you can keep multiple revisions on your server and roll back if necessary.
And you gain the advantage, that on long rsync runs, the website is not in a unsafe file-version state (50% of copy finished), because the switch to the new version is done after the rsync is finished.

Im using it for the following tasks:

  • deploy new version
  • run remote tasks for building (i know, not possible in all environments, but this can be done locally (on the build server) as well)
  • symlink shared folders
  • clear typo3 cache (coreapi)
  • change current-symlink to new version

The concept of the shared folders is very nice.
Im using it for typo3temp, fileadmin, uploads, etc.

So my server folder structure is:

  • releases
    • timestamp-1
    • timestamp-2
  • shared
    • typo3temp
    • fileadmin
    • uploads
  • current (symlink to releases/last-time-stamp)

The vhost webroot is current/htdocs in my case.

All my releases share the fileadmin etc by symlink.

Im really happy with shipit so far;-)

Greetings,
Benny

@malteriechmann
Copy link

Thanks. Helped us setting up CI for a Flow project.

@ludwigmair
Copy link

hi,
i have tryed shipit today and it does not work. it does not connect to the server so far
would be great to get some help
best regards

ludwig

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment