Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

git & Variables

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

With PHP setup, it's time to actually pull down our code onto the server. Let's think about what this process will look like. First, we need to create a directory. Then we need to clone our code with Git. Well there are several ways to get code onto a machine - but using Git is a really nice option.

The file Module

Let's create that directory. Not surprisingly, Ansible has module for this. Search for the "Ansible file module". Yes! This helps set attributes on files, symlinks and directories. If you need to create any of these or set permissions, this is your friend.

The most important option is path, but there are few other we'll need, like state, where you choose what type of "thing" the path should be, and also, owner, group and mode for permissions goodness.

You know the drill: create a new task: Create a project directory and set its permissions. Use become: true, use file and set path to, how about, /var/www/project. The state should be directory and add owner: vagrant and group: vagrant:

---
- hosts: vb
tasks:
... lines 5 - 70
- name: Create project directory and set its permissions
become: true
file:
path: "/var/www/project"
state: directory
owner: "vagrant"
group: "vagrant"
... lines 78 - 79

This will let our SSH user write these files.

Tip

In some setups, you might want to have your web-server user - e.g. www-data - be the owner if this directory. Then, you can use become: www-data on future calls to become that user.

Oh, and set recurse: true - in case /var/www doesn't exist, it'll create that!

---
- hosts: vb
tasks:
... lines 5 - 70
- name: Create project directory and set its permissions
become: true
file:
path: "/var/www/project"
state: directory
owner: "vagrant"
group: "vagrant"
recurse: yes

Referencing Variables

But don't try this yet! Thanks to our hosts.ini setup, we've told Ansible that we want to SSH as the user vagrant. We did that by overriding a built-in variable called ansible_user. Well, guess what? We can reference that same variable in our playbook! Instead of hardcoding vagrant, use Jinja: {{ ansible_user }}. Repeat that next to group:

---
- hosts: vb
tasks:
... lines 5 - 70
- name: Create project directory and set its permissions
... line 72
file:
... lines 74 - 75
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
... lines 78 - 79

Start up your playbook!

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

The git Module

While we're waiting, let's move to the next step: cloning our code via Git. Unfortunately, Ansible does not have a Git module to help us... bah! Just kidding, it totally does! Search for the "Ansible git module" to find it.

The module does have Git as a requirement - but we already installed that. So our job is pretty simple: pass it the repo we want to clone, and the dest-ination we want to clone to.

Do it! Go to http://github.com/symfony/symfony-standard. To start, we'll pull down the Symfony Standard Edition instead of our MooTube code. But that's just temporary. I'll click the "Clone" button and copy the URL.

Now, add a task: Checkout Git repository:

---
- hosts: vb
tasks:
... lines 5 - 79
- name: Checkout Git repository
... lines 81 - 85

We do not need become: true because we own the destination directory. Go straight to git, then repo set to the URL we just copied. For dest, put /var/www/project. Add force: yes: that'll discard uncommitted changes if there are any:

---
- hosts: vb
tasks:
... lines 5 - 79
- name: Checkout Git repository
git:
repo: https://github.com/symfony/symfony-standard.git
dest: "/var/www/project"
force: yes

Head back to your terminal. Sweet! The directory was created! In the VM, the /var/www/project directory is empty.

Creating a Variable

Before we run the new git task, I want to solve one last thing: we have duplication! The directory name - /var/www/project is in two places:

---
- hosts: vb
tasks:
... lines 5 - 70
- name: Create project directory and set its permissions
... line 72
file:
path: "/var/www/project"
... lines 75 - 79
- name: Checkout Git repository
git:
... line 82
dest: "/var/www/project"
... lines 84 - 85

Lame!

Well, good news: in addition to overriding variables - like ansible_user - we can create new variables.

Go all the way to the top of the file - right below hosts - though the order doesn't matter. Add a new vars: key, then below, set symfony_root_dir: /var/www/project:

---
- hosts: vb
vars:
symfony_root_dir: /var/www/project
... lines 6 - 88

Copy that new variable name and use it just like before: {{ symfony_root_dir }}. Repeat that next to dest:

---
- hosts: vb
vars:
symfony_root_dir: /var/www/project
tasks:
... lines 8 - 73
- name: Create project directory and set its permissions
... line 75
file:
path: "{{ symfony_root_dir }}"
... lines 78 - 82
- name: Checkout Git repository
git:
... line 85
dest: "{{ symfony_root_dir }}"
... lines 87 - 88

Ok, now I'm happy. Move over and try the playbook!

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

Looks good! Check the directory in the VM:

ls /var/www/project

Got it! The code is here, but it's not working yet: we need to install our Composer dependencies!

Leave a comment!

14
Login or Register to join the conversation
Abdul mannan Avatar
Abdul mannan Avatar Abdul mannan | posted 2 years ago

I am using the repo link https://github.com/symfony/... for symfony 5. It seems like it is missing the bin/console. I have tried composer require symfony/console but still don't get it.

Just wanted to know if there should be a different way to do the installation for symfony and on wards?

Reply

Hey Abdul mannan

Here is a tip https://symfony.com/doc/cur...
You can use both ways described in docs it works perfectly!

Cheers!

Reply
Default user avatar
Default user avatar Boran Alsaleh | posted 5 years ago

Hi , I would like to ask a Q, i have updated some code in vendor bundle , Is there a way to avoid updating this bundle from composer when I do deployment. Thnx

Reply

Hey Boran,

Sounds not good. Do you mean you did some changes manually in vendor/ directory? If so, that's not the correct way, you should never change directly any third-party code which is inside vendor/ dir - it's totally unsafe to do as you can see. The proper way is to send a PR to the package owner if your changes fix or improve some things, but if you need to make changes related only to your project, you can fork that package, do the changes you need in the fork and then points Composer to your fork with provided fix. If you need more info about it - I can provide a simple example.

But back to your question, if you modify vendor dir (which is very bad as I mentioned) - you're not able to run composer install/update commands anymore. The only way to deploy this broken application is to upload the entire vendor/ directory to the host. But that's a bad idea.

Cheers!

Reply
Default user avatar
Default user avatar Boran Alsaleh | Victor | posted 5 years ago

Hi Victor ,

thanks for your Answer , I have modified this code in order to be compatible with the system requirement , not to fix a bug , could you please give me an example how i can avoid that.

Best Regards ,

Reply

Hey Boran,

If it might be helpful for others - I think you can suggest your changes to be included in the repo by sending a PR.

What about example, you can tell Composer to look at your fork by specifying URL to your forked repo in composer.json this way:


{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/your-github-nickname/package-name.git"
        }
}

Where "https://github.com/your-github-nickname/package-name.git" is a link to your fork of the repo. In "require" section you need to just tweak the version constraint of this package, the name remains the same, for example, if you push changes to master, than you need to use "dev-master" instead of constraint like "^v1.2.3".

Cheers!

Reply
Default user avatar

I looked into the finished Ansistrano Zip File. We additionally added mode: 0775 to the "Create project directory" module; What does this actually mean?

Reply

Hey Chris,

If you're wondering about that magical 0775 number - it's a permissions level in Linux OS, where "77" means you allow to read/write/execute for owners and groups, and "5" means you allow to read/execute only for others. So with that task we create a project directory with "755" permissions. If you want more information - read about chmod linux command: https://en.wikipedia.org/wi...

Cheers!

Reply
Default user avatar
Default user avatar jian su | posted 5 years ago

hi Guys:

When I checkout bitbucket, it will require me to enter my account password my checkout will stuck forever and waiting me to enter password. How Do I automatic that in Ansible?

Reply

Hey Jian,

Unfortunately, Ansible not able to fill interactive user prompts, that's why we add "--no-interactive" option in some Symfony commands. So you need to handle private repositories in a bit different way, i.e. use SSH key - you can add it in Bitbucket Settings / SSH keys. Also Bitbucket has another cool feature: "Access keys" - in your *repository* settings go to "Access keys" and add one. This access keys provide read-only access to your repository which is perfect for deployment.

Cheers!

Reply
Default user avatar

well, that is kinda suck. For pulling down bitbucket I can use SSH keys no problem. Think about this situation. In a large enterprise, it is reasonable to ask sysadmins to have different passwords on each node. let's say have different passwords on 1000 nodes. Implementing that would be near impossible. we need a solution to store those keys or password inside Ansible , then when we deploy 1000 nodes we don't need to enter password. when configure server, you need to do alot interactive user prompts for other tasks. Just my thought and I think this is valid question.

Reply

Hey Jian,

Ansible has a really great solution for it - the Vault, which helps you to store sensitive data like your DB credentials, passwords, secret tokens, etc. - you will discover it a bit later in this course, check it out here: https://knpuniversity.com/s... . But if we talk about connection to the server - you probably won't use plain passwords. Instead, SSH key is something that you need. And anyway, you need to configure connection to each of 1000 servers if they have different passwords / SSH keys on them.

Cheers!

Reply
Nizar Avatar

Hey Victor,
can you do a course on Continuous Integration of a Symfony project with Jenkins ?

Reply

Hey Nizar!

Interesting idea! We currently use CircleCI for our continuous integration on SymfonyCasts... and GitHub actions is gaining popularity fast for the same thing (and i use that for many of my open source libraries). These are both "hosted", so they're easier to use than Jenkins (but of course, it will cost you some money). I don't see Jenkins being used nearly as often as it was a few years ago.

Let me know if this helps :).

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built using an older version of Symfony, but the core concepts of Ansible are still valid. New versions of Ansible may contain some features that we don't use here.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.12
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.0
        "snc/redis-bundle": "^2.0", // 2.0.0
        "predis/predis": "^1.1", // v1.1.1
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.8
        "symfony/phpunit-bridge": "^3.0", // v3.1.4
        "doctrine/data-fixtures": "^1.1", // 1.3.3
        "hautelook/alice-bundle": "^1.3" // v1.4.1
    }
}
userVoice