I am making a deployment script using GitLab's CD. I've got a script:
- ssh USER@HOST "cd domains/$DOMAIN/ && mkdir build-$CI_JOB_ID"
- rsync -ar --port=22 * USER@HOST :domains/$DOMAIN/build-$CI_JOB_ID
- ssh USER@HOST "cd domains/$DOMAIN/ && ln -sfv build-$CI_JOB_ID/public public_html && ls -la"
- ssh USER@HOST "cd domains/$DOMAIN/ && ls | grep '^build\-.*$' | grep -Ev '^build-$CI_JOB_ID$' | xargs rm -rf"
everything works fine but not ln
command. It works only 50% of the time. Here are logs from ` jobs runnning one after another.
Job 1 with $CI_JOB_ID = 76337215
worked properly. Link is correct.
$ ssh USER@HOST "cd domains/$DOMAIN/ && ln -sfv build-$CI_JOB_ID/public public_html && ls -la"
public_html -> build-76337215/public
total 20
drwx--x--x 5 USER 1000 7 Jun 20 22:15 .
drwx--x--x 23 USER 1000 23 Jun 19 16:34 ..
-rw-r--r-- 1 USER 1000 39 Jun 17 22:12 .htaccess
drwxr-xr-x 12 USER 1000 20 Jun 20 22:07 build-76335972
drwxr-xr-x 12 USER 1000 20 Jun 20 22:14 build-76337215
drwxr-xr-x 2 USER 1000 4 Jun 20 11:48 logs
lrwxr-xr-x 1 USER 1000 21 Jun 20 22:15 public_html -> build-76337215/public
Job 2 with $CI_JOB_ID = 76339729
did not work. Link is still to old 76337215
from Job 1.
$ ssh USER@HOST "cd domains/$DOMAIN/ && ln -sfv build-$CI_JOB_ID/public public_html && ls -la"
public_html/public -> build-76339729/public
total 20
drwx--x--x 5 USER 1000 7 Jun 20 22:28 .
drwx--x--x 23 USER 1000 23 Jun 19 16:34 ..
-rw-r--r-- 1 USER 1000 39 Jun 17 22:12 .htaccess
drwxr-xr-x 12 USER 1000 20 Jun 20 22:14 build-76337215
drwxr-xr-x 12 USER 1000 20 Jun 20 22:28 build-76339729
drwxr-xr-x 2 USER 1000 4 Jun 20 11:48 logs
lrwxr-xr-x 1 USER 1000 21 Jun 20 22:15 public_html -> build-76337215/public
What I am doing wrong? Why it is not working 100% of the time?
The problem is that if public_html
already exists and is a directory (or a symlink to a directory), then your ln
command creates a new link in that directory, rather than replacing public_html
.
Use the -T
option to avoid this:
ln -sfTv build-$CI_JOB_ID/public public_html
alternately, you can use the -n
option to not dereference a link
ln -sfnv build-$CI_JOB_ID/public public_html
this will replace public_html
if it is a symlink and create the symlink in the subdirectory if it is a real directory (-T would give an error in the latter case).