0

I have to manage different variants of a software (in this case PHP+CSS+JS) in Gitlab for different "customers" (in this case non-profit associations). The differences are limited to a few files (3 files), the rest is the same for all customers. But in these three files I often have to make changes.

Now I want to transport via gitlab CI/CD the respective software + the specific variants of the files to the different servers (for each customer). And always, if I change something at branch main or at a customer-specific file I like to push the changes to the server via gitlab CICD. (For now only to the respective staging system, production only triggered manually).

What is a good and simple way to do this? My first approaches:

  • Old-fashioned: One directory per client for these files and then copy them manually per client per shell. Disadvantage: Does not work with repro/git pull on the server (which I currently use), because git would grumble on the next run because of locally modified files. So I would have to change the pipeline to rsync. And that is not a very nice solution...
  • Maintain all clients in a separate branch, in the main pipeline do an automatic merge from main to the client branch on delivery (only locally inside the docker container) and push the result to the servers. Problem: The pipeline fails on merge conflicts.
  • The commit to main triggers an automatic merge for the corresponding branches. Only these then trigger the appropriate pipelines for each customer. (No experience of doing multiple merges from CI/CD to other branches!) (The difference with the above option is that the push to the server is done in the branch pipeline, not the main pipeline as above).
  • Move the three files out to a separate repo per client, separate pipelines.(... too many repo's)
  • Create a git patch from the customisations for each client and apply it to the pipeline. Disadvantage: every time a change is made, the patch has to be rebuilt. (Unless I also create it in the pipeline). ... for sure there are more possibilities

I'm familiar with basically git pipelines, so I don't need a complete solution as code (I also like to take) but just a description of the best (or a good) way. For me the 3rd solution (automatic merge in the customer branches) looks best. (even I don't now how to do that)

mkours
  • 390
  • 2
  • 11
  • `because locally changed files` ? Don't change files locally. If you do, synchronize with git. – KamilCuk May 30 '23 at 14:06
  • What I would do is maintain three different branches for the 3 different variants. Make changes in those branches when needed and deploy them separately. I think u have mentioned a similar solution but i didnt get the issue you have mentioned. – Origin May 31 '23 at 04:22

1 Answers1

0

After reading more in various posts, I decide to use the third option (automatic merge). But merging inside a pipeline isn't so simple. More precisely: The merge itself is easy, but pushing the result is difficult. See How do I merge branches using GitLab CI/CD? and How do I push to a repo from within a gitlab CI pipeline? But dealing with all that ssh/token stuff is not my favourite solution. So my next idea was to use that with the job token (which is pretty much easier) that I'm used to. But with job tokens you can do many things - accept to push to a repro :-( See: https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html But the gitlab team is working on it, see: Issue.

So I decide to go for option 3, but on the first set do the merges half-manually (with a local script that does the merge and push) and wait for the solution with the job token.


After some more tests I decide to move to the second option: So my main pipeline does all that stuff. Every time I do a push on main the pipeline merges that for all customers, each get a section like this.

demo_automerge:
  stage: automerge
  script:
    - apk update && apk add git
    - git config user.name "CI Pipeline"
    - git config user.email "cipipeline@example.com"
    - git fetch --all
    - git checkout demo_automerge
    - git merge origin/main
    - lftp -c "set ftp:ssl-allow yes; open -u $WPDEMO_USER,$WPDEMO_PW $WPDEMO_HOST;  mirror -Rv ./ ./www --ignore-time --parallel=10 --exclude-glob .git* --exclude .git/"
  environment:
    name: demo
    url: http://wp.demo.de

  only:
    - main
 #   - demo_automerge
  artifacts:
    expire_in: 1 month

The advantage is that I don't have to write anything back to the repository. But via the artifacts it is traceable what was deployed.

mkours
  • 390
  • 2
  • 11