br0ken- / cikit Goto Github PK
View Code? Open in Web Editor NEWContinuous Integration Kit (CIKit)
Home Page: https://cikit.tools
License: Apache License 2.0
Continuous Integration Kit (CIKit)
Home Page: https://cikit.tools
License: Apache License 2.0
Try to reduce system resources cpus
and memory
in case if you're seeing this error.
Might be helpful: http://druss.co/2015/06/fix-vt-x-is-not-available-verr_vmx_no_vmx-in-virtualbox/
cikit-mssql
role which will install the MSSQL server (https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup, https://docs.microsoft.com/en-us/sql/linux/sample-unattended-install-redhat, https://www.microsoft.com/en-us/sql-server/developer-get-started/php/ubuntu).cikit-mssql
role to cikit-php
to install sqlsrv
and pdo_sqlsrv
extensions for PHP 7+. Use sybase
extension for PHP 5.6 which provides mssql_*
functions.https://<PROJECT>.loc
doesn't work in WSL (while port 80
is ok the 443
even not appears in server logs).%SYSTEMROOT%\system32\drivers\etc\hosts
automatically running Vagrant in WSL.issues/52
by the master
in WSL docs once PR will be merged.Resolution of known problem
section from WSL docs when the problem will be gone.Run cikit self-update --version=issues/52
before creating projects via cikit init
and provisioning VM via vagrant up
. It's important.
cikit-platformsh-cli
role for installing the https://github.com/platformsh/platformsh-cli.platformsh-cli
.For instance, CIKit droplet could be just a host for MSSQL database which is accessible at the 1433
port. We should extend ports forwarding configuration and use NGINX TCP forwarding to accomplish this.
Right now we have a documentation to create a matrix of CI servers and a droplet in it afterward. But what if I don't want to use matrix and just have a VPS somewhere?
The documentation should describe the addition of VPS's credentials using cikit host/add
, provision of the CI server and storing the SSH credentials within the project directory.
cikit-pantheon-terminus
role for installing the Terminus.cikit-webserver
role with the configuration for serving the virtual hosts.fastcgi_pass
to PHP-FPM.VirtualDocumentRoot
to be able opening project's builds on subdomains.apache2
nginx
apache2
nginx
cikit
requires Ansible to be installed on a controlling system which means that Python is available. Let's use it because Bash logic starts becoming complex.
Right after provisioning the Safe HTML
markup formatter is disabled and some parts of UI looks ugly due to this.
The fix is pretty easy (changing value at http://HOST/jenkins/configureSecurity/), but needs to get rid of requirement to do this manually.
Follow up to #67
Downloading from preferred mirror can potentially fail. In this case would be really nice to retry download from alternative mirrors.
git add composer.json composer.lock
git commit -m '[composer update][skip tests] Update Composer dependencies'
Created in a such way commit must to be recognized by Jenkins which should extract the composer update
and skip tests
actions from the message and pass them to Ansible playbook as an array. Further logic to handle the actions must be built in there.
There is an issue with the latest version of CIKit when trying to provision a local virtual machine. Steps to reproduce:
curl -LSs https://raw.githubusercontent.com/BR0kEN-/cikit/master/install.sh | bash
cikit init --project=dummyproject
vagrant up --provision
After these steps a corresponding VirtualBox VM will be turned on and a provision script will ask which versions of packets to install. Right after this, Python will throw an error and provisioning will stop:
==> default: Running provisioner: cikit...
Which version of PHP you'd want to install? (5.6/7.0/7.1) [5.6]:
Which version of Node.js you'd want to install? (4/5/6/7) [6]:
Which version of Ruby you'd want to install? (2.1.10/2.2.6/2.3.3/2.4.0) [2.4.0]:
Which version of Solr you'd want to install? (5.5.5/6.6.2/no) [6.6.2]:
Do you want to install Microsoft SQL Server? (yes/no) [no]:
Traceback (most recent call last):
File "/usr/local/share/cikit/lib/cikit", line 20, in <module>
import __init__
File "/usr/local/share/cikit/lib/__init__.py", line 107, in <module>
'import yaml, json\nprint json.dumps(yaml.load(open(\'%s\')))' % ENV_CONFIG,
File "/usr/local/share/cikit/lib/functions.py", line 28, in call
return Popen(nargs, stdout=PIPE, **kwargs).stdout.read().rstrip()
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
CIKit provisioner responded with a non-zero exit status.
The host environment:
Ubuntu 16.04.3 LTS (Linux 4.4.0-109-generic)
VirtualBox 5.1.32
Vagrant 1.9.5
Python 2.7.12
Ansible 2.4.2.0
As we've figured out, there is a correct environment.yml
file in the project's directory and the condition os.path.isfile(ENV_CONFIG) is satisfied.
The issue doesn't affect the provisioning process of a remote CI server.
According to the https://medium.engineering/use-a-dev-domain-not-anymore-95219778e6fd, the *.dev
domain is no longer available without SSL. Let's switch to *.loc
.
We have a well-done structure of the PROJECT_DIR/.cikit/inventory
so we can easily form it automatically. All unique data we need - credentials to the droplets host.
Download from Ukrainian mirror while located in Ukraine:
time wget http://apache.volia.net/lucene/solr/6.6.2/solr-6.6.2.tgz
--2017-11-22 17:34:47-- http://apache.volia.net/lucene/solr/6.6.2/solr-6.6.2.tgz
Resolving apache.volia.net... 82.144.192.7, 82.144.192.7
Connecting to apache.volia.net|82.144.192.7|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 147343211 (141M) [application/x-gzip]
Saving to: ‘solr-6.6.2.tgz.1’
solr-6.6.2.tgz.1 100%[================================================================================================================>] 140.52M 8.62MB/s in 15s
2017-11-22 17:35:02 (9.40 MB/s) - ‘solr-6.6.2.tgz.1’ saved [147343211/147343211]
real 0m15.214s
user 0m0.112s
sys 0m0.974s
Download from the original location while located in Ukraine:
time wget http://archive.apache.org/dist/lucene/solr/6.6.2/solr-6.6.2.tgz
--2017-11-22 17:34:09-- http://archive.apache.org/dist/lucene/solr/6.6.2/solr-6.6.2.tgz
Resolving archive.apache.org... 163.172.17.199
Connecting to archive.apache.org|163.172.17.199|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 147343211 (141M) [application/x-gzip]
Saving to: ‘solr-6.6.2.tgz’
solr-6.6.2.tgz 62%[=====================================================================> ] 87.60M 53.1KB/s eta 22m 5s
Result: 100%/15 sec. vs 62%/22 min. I think comments are unnecessary.
Needs to add provisioning for installing Java 8 since Jenkins 2.54 requires it.
I'm trying to setup cikit project, but when I run vagrant up
I get the following error:
TASK [Install EasyInstall and PIP] *********************************************
failed: [default] (item={u'tool': u'easy_install', u'script': u'curl -s https://raw.githubusercontent.com/ActiveState/ez_setup/v0.9/ez_setup.py | python'}) => {"changed": true, "cmd": "[ $(which easy_install) ] || curl -s https://raw.githubusercontent.com/ActiveState/ez_setup/v0.9/ez_setup.py | python", "delta": "0:00:00.760523", "end": "2017-11-01 05:09:10.169754", "failed": true, "item": {"script": "curl -s https://raw.githubusercontent.com/ActiveState/ez_setup/v0.9/ez_setup.py | python", "tool": "easy_install"}, "msg": "non-zero return code", "rc": 1, "start": "2017-11-01 05:09:09.409231", "stderr": "Downloading http://pypi.python.org/packages/source/d/distribute/distribute-0.6.14.tar.gz\nTraceback (most recent call last):\n File \"<stdin>\", line 485, in <module>\n File \"<stdin>\", line 480, in main\n File \"<stdin>\", line 193, in download_setuptools\n File \"/usr/lib/python2.7/urllib2.py\", line 154, in urlopen\n return opener.open(url, data, timeout)\n File \"/usr/lib/python2.7/urllib2.py\", line 435, in open\n response = meth(req, response)\n File \"/usr/lib/python2.7/urllib2.py\", line 548, in http_response\n 'http', request, response, code, msg, hdrs)\n File \"/usr/lib/python2.7/urllib2.py\", line 473, in error\n return self._call_chain(*args)\n File \"/usr/lib/python2.7/urllib2.py\", line 407, in _call_chain\n result = func(*args)\n File \"/usr/lib/python2.7/urllib2.py\", line 556, in http_error_default\n raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)\nurllib2.HTTPError: HTTP Error 403: SSL is required", "stderr_lines": ["Downloading http://pypi.python.org/packages/source/d/distribute/distribute-0.6.14.tar.gz", "Traceback (most recent call last):", " File \"<stdin>\", line 485, in <module>", " File \"<stdin>\", line 480, in main", " File \"<stdin>\", line 193, in download_setuptools", " File \"/usr/lib/python2.7/urllib2.py\", line 154, in urlopen", " return opener.open(url, data, timeout)", " File \"/usr/lib/python2.7/urllib2.py\", line 435, in open", " response = meth(req, response)", " File \"/usr/lib/python2.7/urllib2.py\", line 548, in http_response", " 'http', request, response, code, msg, hdrs)", " File \"/usr/lib/python2.7/urllib2.py\", line 473, in error", " return self._call_chain(*args)", " File \"/usr/lib/python2.7/urllib2.py\", line 407, in _call_chain", " result = func(*args)", " File \"/usr/lib/python2.7/urllib2.py\", line 556, in http_error_default", " raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)", "urllib2.HTTPError: HTTP Error 403: SSL is required"], "stdout": "", "stdout_lines": []}
failed: [default] (item={u'tool': u'pip', u'script': u'easy_install pip'}) => {"changed": true, "cmd": "[ $(which pip) ] || easy_install pip", "delta": "0:00:00.003229", "end": "2017-11-01 05:09:10.794231", "failed": true, "item": {"script": "easy_install pip", "tool": "pip"}, "msg": "non-zero return code", "rc": 127, "start": "2017-11-01 05:09:10.791002", "stderr": "/bin/bash: easy_install: command not found", "stderr_lines": ["/bin/bash: easy_install: command not found"], "stdout": "", "stdout_lines": []}
PLAY RECAP *********************************************************************
default : ok=11 changed=2 unreachable=0 failed=1
Here is a link to Stack overflow: https://stackoverflow.com/questions/46967488/getting-error-403-while-installing-package-with-pip
Currently, during provisioning the VM, all answers on questions are storing in file inside of .vagrant
directory, which is completely personal for every particular user.
The idea is to have this YAML file available within project directory with ability to commit it to VCS to automatically inform every team member about environment configuration changing.
Currently, every CI server is a separate VM with Ubuntu 16.04. Host machine has the same OS of the same version. In order to reduce overhead bringing by the every VM we should switch to containers which will be provisioned in the same way as we did for VMs.
*_PR_BUILDER
jobs.PHP 7.2 has been released on November 30, 2017. Due to this, we ought to consider its inclusion into CIKit, but right after XDebug 2.6 will be released in order to provide a full development stack.
Currently it's allowed to have only one Selenium grid, so you need to halt other projects for tests run. Also, the selenium
service must be reworked since Ubuntu 16.04 has the systemd
which does not allow to pass arguments to service.
Those, who haven't added a host using cikit host/add
might not have the .hosts.json
that will make an entire inventory to be not formed at all. This is a follow-up for the #87.
Now we're copying the docroot
only to the /var/www/BUILD_ID
and this might bring some implications due to missing files. For instance, Composer packages or Drupal 8 configs, for now, forced to be lying in the docroot
instead of the directory above it.
https://ci_server.com/project_build_1
to be changed by https://project_build_1.ci_server.com
. This is a mandatory change allowing to use the VirtualDocumentRoot
on CI server.http://project_build_1.localhost:8080
accessible within the local network for running tests (or for anything else without basic HTTP auth).cikit-apache
ansible-role-mysql
cikit-mysql-config
cikit-mysql
cikit-ruby
cikit-jetty-solr
cikit-solr
cikit-jenkins
cikit-java
PermitRootLogin
set to prohibit-password
(item 4 in https://github.com/BR0kEN-/cikit/tree/issue-25/docs/vagrant/box).matrix/domain
At the moment, to use SQL workflow via SSH, every project member must have defined the parent host (SSH credentials to a matrix).
In order to be able to connect to CI server from local machine or VM, you must know the hostname, port, user and have a private SSH key. If the credentials for a droplet is shared then the port number can be automatically obtained from the droplet's name (e.g. cikitNN
where NN
is a serial number of a port), the user will be root
by default, a key will be stored in a directory and only the hostname for a matrix remains unknown. To overcome this we can share the hostnames in projects as well.
Every teammate must do something like cikit host/add --alias=matrixName --domain=example.com --ssh-key=/path/to/private.key
before the entire scheme will start working. This is a security problem since as less as possible users must have the credentials to Matrix.
The provisioning of a VM attempts to run the cikit selenium
with the --limit=<VM_NAME>
option and it ends up with the next message because the playbook is designed to run on localhost only.
PLAY [localhost] ***************************************************************
skipping: no hosts matched
For the moment we're installing Ruby using rbenv install
and this process can get some boost by avoiding generation the ri/RDoc documentation.
rbenv/ruby-build#1054 (comment) or https://coderwall.com/p/zrrxna/speed-up-building-ruby
2.5.0
.RUBY_CONFIGURE_OPTS="--disable-install-doc"
environment variable to avoid building docs.cikit init --project=tolik
.cikit provision --list-tags
to CIKIT_LIST_TAGS=true cikit provision
to not mix custom playbook options with the options for ansible-playbook
.cikit provision --tags=tag1,tag2,tagN
to CIKIT_TAGS="tag1,tag2,tagN" cikit provision
to not mix custom playbook options with the options for ansible-playbook
.ANSIBLE_ARGS
environment variable because we're forming a set of options for the ansible-playbook
by some logic and this variable may contain a raw set of arguments which will conflict with necessary ones.--limit
option for the cikit
utility which is a passthrough to ansible-playbook
.CIKIT_VERBOSE
environment variable allowing to add -vv
to the ansible-playbok
when defined.CIKIT_VERBOSE
and use ANSIBLE_VERBOSITY
(https://github.com/ansible/ansible/blob/devel/lib/ansible/config/base.yml#L1126).%SystemRoot%\system32\drivers\etc\hosts
: agiledivider/vagrant-hostsupdater#89 (comment). Also, in case of Cygwin, user can run it as an administrator (sudo
replacement under Cygwin).As a follow-up for the https://github.com/BR0kEN-/cikit/issues/49 we can introduce a new nice improvement.
The web-server.yml has the list of virtual hosts, e.g.:
web_server_vhosts:
# Serve "project.loc" in the "docroot".
- name: "{{ project }}"
root: "docroot"
- name: "subdomain.{{ project }}"
root: "subdomain-docroot"
The configuration above will produce two virtual hosts (for any chosen web server) for serving project.loc
from /var/www/docroot
and subdomain.project.loc
from /var/www/subdomain-docroot
.
The problem here is that only project.loc
will be added to /etc/hosts
by the vagrant-hostsupdater
plugin by reading a value from the config.vm.hostname in the Vagrantfile. The subdomain.project.loc
with a corresponding IP should be added manually and it's a flaw due to automatic IP resolution: when IP gets updated the entry won't remain working.
Disallow Ansible logic and variable usage within the web_server_vhosts
variable. This will allow using plain-text values in config.hostsupdater.aliases
at Vagrantfile for adding necessary records to /etc/hosts
.
A new look of the file:
---
# WARNING! Do not use any variables or logic within the "web_server_vhosts"
# variable. It must be plain as used as a source for creating aliases for
# VM's VPN by just reading the YAML structure of this file without any
# Ansbile/Jinja2 evaluation.
#
# The "{{ project }}.loc" will be served from the "/var/www/docroot" without
# any configuration here.
#
# Serve "subdomain.{{ project }}.loc" from the "/var/www/subdomain".
# - name: subdomain
web_server_vhosts: []
Read the web_server_vhosts
from the web-server.yml
of a project and form an array of aliases for the vagrant-hostsupdater
Vagrant plugin.
Adjust logic of creating virtual hosts (nginx
and apache2
).
Update the documentation.
Add the changelog record.
Do not ship provisioning, cikit
utility, Vagratfile
, provisioners and other important stuff which becomes outdated when CIKit gets an update.
/usr/local/share/cikit
and automatic creation of symlink to cikit
utility.Vagrantfile
which will have an include of /usr/local/share/cikit/vagrant/Vagrantfile
.provision
process.cikit self-update
to grab latest updates of CIKit.cikit
package to CI server.cikit repository
by cikit init
and initialize a project in CWD.At the moment the host for droplets can be created by cikit matrix/matrix --limit=HOST
. The command is simple and explicit, unlike the command to list/add/start/stop/restart/delete droplet(s) - CIKIT_TAGS="vm" cikit matrix/matrix --limit=HOST --droplet-[list|add|start|stop|restart|delete]
.
Despite on confusing matrix/matrix
in both of cases, you can easily forget to add CIKIT_TAGS="vm"
and run host provisioning once again. This takes much more time.
matrix/provision --limit=HOST
to provision the host.matrix/droplet --limit=HOST --droplet-<ACTION>
to manage the droplets.matrix/*
directory to cikit
utility.On old images apt cache might be completely out of date which results in failure on "Install APT packages" step of "provision.yml" script.
vagrant@test:~$ cikit reinstall
PLAY [localhost] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Set path to directory, where project accessible from web] ********************************************************************************************************************************************
ok: [localhost]
TASK [Set path to directory, where project codebase located] ***********************************************************************************************************************************************
ok: [localhost]
TASK [Set path to reports directory and URL by which they will be accessible] ******************************************************************************************************************************
ok: [localhost]
TASK [Ensure that project directory has correct permissions] ***********************************************************************************************************************************************
ok: [localhost] => (item=/var/www/docroot)
ok: [localhost] => (item=/var/www/docroot/reports)
changed: [localhost] => (item=/var/www/docroot/sites/default)
TASK [Initialize an empty build report] ********************************************************************************************************************************************************************
ok: [localhost]
TASK [Check installation of Composer packages] *************************************************************************************************************************************************************
ok: [localhost]
TASK [Check for composer.json existence] *******************************************************************************************************************************************************************
ok: [localhost]
TASK [Install Composer packages] ***************************************************************************************************************************************************************************
TASK [Check existence of installation mode] ****************************************************************************************************************************************************************
ok: [localhost]
TASK [Check existence of environment configuration] ********************************************************************************************************************************************************
ok: [localhost]
TASK [Obtain home directory of a user, who triggered this script] ******************************************************************************************************************************************
changed: [localhost]
TASK [Set the user's home directory] ***********************************************************************************************************************************************************************
ok: [localhost]
TASK [Ensure directory for backup data exists] *************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "gid": 80, "group": "80", "mode": "0777", "msg": "chown failed: [Errno 1] Operation not permitted: '/var/www/backup'", "owner": "501", "path": "/var/www/backup", "size": 68, "state": "directory", "uid": 501}
...ignoring
TASK [Seek for SSH keys] ***********************************************************************************************************************************************************************************
ok: [localhost]
TASK [Copy SSH keys] ***************************************************************************************************************************************************************************************
TASK [include_vars] ****************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Compute actions to run] ******************************************************************************************************************************************************************************
ok: [localhost] => (item=composer)
ok: [localhost] => (item=npm)
TASK [include_tasks] ***************************************************************************************************************************************************************************************
included: /var/www/scripts/tasks/reinstall/actions/packages-install.yml for localhost
TASK [include_tasks] ***************************************************************************************************************************************************************************************
included: /var/www/scripts/tasks/reinstall/actions/cache-get.yml for localhost
TASK [Check for Composer packages in cache] ****************************************************************************************************************************************************************
ok: [localhost]
TASK [Check for Composer packages at place] ****************************************************************************************************************************************************************
ok: [localhost]
TASK [Check whether Composer packages should be reinstalled] ***********************************************************************************************************************************************
ok: [localhost]
TASK [Copy Composer packages from cache] *******************************************************************************************************************************************************************
TASK [Check for /var/www/docroot/composer.json] ************************************************************************************************************************************************************
ok: [localhost]
TASK [Install Composer packages] ***************************************************************************************************************************************************************************
TASK [include_tasks] ***************************************************************************************************************************************************************************************
TASK [include_tasks] ***************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"failed": true, "reason": "'is_reinstall_mode' is undefined"}
PLAY RECAP *************************************************************************************************************************************************************************************************
localhost : ok=22 changed=2 unreachable=0 failed=1
- debug: var=is_reinstall_mode
right before the include_tasks
the correct value of the variable will be shown.- include_tasks: "tasks/reinstall/modes/full.yml"
the new error will appear:fatal: [localhost]: FAILED! => {"failed": true, "msg": "The task includes an option with an undefined variable. The error was: 'state' is undefined\n\nThe error appears to have been in '/var/www/scripts/tasks/database/database.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n- name: \"{{ name | default('command') }}\"\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: 'state' is undefined"}
For now we're living looking at the next warning during provisioning:
[DEPRECATION WARNING]: The use of 'include' for tasks has been deprecated. Use
'import_tasks' for static inclusions or 'include_tasks' for dynamic inclusions.
This feature will be removed in a future release. Deprecation warnings can be
disabled by setting deprecation_warnings=False in ansible.cfg.
But https://github.com/jdauphant/ansible-role-nginx has been updated and now supports Ansible 2.4.x. So let's update the package.
cmfs
variable dynamically: add main.yml
within cmf/drupal
and cmf/wordpress
and scan for those files.For now the result of the cikit matrix/droplet --limit=matrix1 --droplet-add
is unclear since you can't realize which droplet has been just created.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.