ahalogy-automation 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +18 -0
- data/ahalogy-automation.gemspec +12 -0
- data/bin/a5y-configure +150 -0
- data/data/ahalogy-automation/vimrc +116 -0
- data/lib/ahalogy/install-helper.rb +88 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 768e3fbe0672c4df5608294a6ebe2c4dfd76d523
|
4
|
+
data.tar.gz: e70518d929d3949f938a0dc9576ebcbf960b2236
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c3972ac991702649e755503496e631845188673ab9a8c17a4ca880e51c87a3a9856b13561ca11cade44a11cb146a2e751fd4a70bc3e439842b0a551c8491f28c
|
7
|
+
data.tar.gz: de18afcb72bb007926d43db033975a6e01db3e6043af7e9d17b2fc8d14938e9c443a38b4efb9f447a4c914387ed046e748e7349cde2a94041f6ff299925a2da0
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
task :default => [:build, :install]
|
2
|
+
|
3
|
+
task :build do
|
4
|
+
`gem build ./ahalogy-automation.gemspec`
|
5
|
+
end
|
6
|
+
|
7
|
+
task :install do
|
8
|
+
gems = Dir['*.gem']
|
9
|
+
`sudo gem install #{gems.first}`
|
10
|
+
end
|
11
|
+
|
12
|
+
task :console do
|
13
|
+
exec "irb -r ahalogy-automation -I ./lib"
|
14
|
+
end
|
15
|
+
|
16
|
+
task :run do
|
17
|
+
ruby "-Ilib", 'bin/a5y-configure'
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'ahalogy-automation'
|
3
|
+
gem.version = '0.0.1'
|
4
|
+
gem.date = '2015-03-23'
|
5
|
+
gem.summary = 'Scripts to handle IT automation.'
|
6
|
+
gem.authors = ['Zan Loy']
|
7
|
+
gem.files = `git ls-files`.split("\n") - %w[.gitignore]
|
8
|
+
gem.executables = ['a5y-configure']
|
9
|
+
|
10
|
+
gem.add_runtime_dependency 'colorize', '~> 0'
|
11
|
+
gem.add_runtime_dependency 'github', '~> 0'
|
12
|
+
end
|
data/bin/a5y-configure
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ahalogy/install-helper'
|
4
|
+
require 'colorize'
|
5
|
+
require 'github'
|
6
|
+
require 'optparse'
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
groups = ['developer', 'pinner', 'cs', 'marketing', 'content']
|
10
|
+
options = {
|
11
|
+
:groups => ['default'],
|
12
|
+
:verbose => false,
|
13
|
+
}
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
groups.each do |group|
|
16
|
+
opts.on("--#{group}", "Install apps for #{group} group.") { options[:groups] << group }
|
17
|
+
end
|
18
|
+
opts.on("-l", "--list", "List available groups.") do
|
19
|
+
puts "Available groups: #{groups.join(', ')}"
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
opts.on("-d", "--debug", "Enable debug messaging.") { options[:verbose] = true }
|
23
|
+
end.parse!
|
24
|
+
|
25
|
+
cleanup = []
|
26
|
+
|
27
|
+
if options[:groups].include? 'default'
|
28
|
+
## Install xcode command line tools
|
29
|
+
system("xcode-select -v")
|
30
|
+
if $? != 0
|
31
|
+
run_cmd "xcode-select --install", "Installing Xcode."
|
32
|
+
else
|
33
|
+
puts "Xcode is already installed...skipped."
|
34
|
+
end
|
35
|
+
system 'xcodebuild &> /dev/null'
|
36
|
+
if $? == 69
|
37
|
+
puts "You need to agree to the Xcode license before continuing...".colorize(:red)
|
38
|
+
system("sudo xcodebuild -license")
|
39
|
+
if $? != 0
|
40
|
+
fail "Xcode is not configured correctly."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Let's setup our sshkey and github (we need this to pull the config repo)
|
45
|
+
if File.exists? File.expand_path("~/.ssh/id_rsa")
|
46
|
+
puts "sshkey exists... skipped."
|
47
|
+
else
|
48
|
+
run_cmd "ssh-keygen -f ~/.ssh/id_rsa -N ''", "Generating sshkey."
|
49
|
+
end
|
50
|
+
|
51
|
+
# Enable FileVault
|
52
|
+
# run_cmd "sudo fdesetup enable -user admin -usertoadd enduser"
|
53
|
+
|
54
|
+
# Enable system firewall
|
55
|
+
run_cmd "sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1", "Enabling firewall."
|
56
|
+
|
57
|
+
# Install homebrew
|
58
|
+
if File.exists? '/usr/local/bin/brew'
|
59
|
+
puts "Homebrew already installed...skipped."
|
60
|
+
else
|
61
|
+
run_cmd 'ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"', "Installing homebrew."
|
62
|
+
end
|
63
|
+
|
64
|
+
# Tap casks
|
65
|
+
install_brew 'caskroom/cask/brew-cask'
|
66
|
+
run_cmd 'brew tap caskroom/cask', "Tapping caskroom/cask..."
|
67
|
+
run_cmd 'brew tap caskroom/fonts', "Tapping caskroom/fonts..."
|
68
|
+
run_cmd 'brew tap caskroom/versions', "Tapping caskroom/versions..."
|
69
|
+
run_cmd 'brew tap homebrew/dupes', "Tapping homebrew/dupes..."
|
70
|
+
run_cmd 'brew tap homebrew/versions', "Tapping homebrew/versions..."
|
71
|
+
|
72
|
+
### Install Applications
|
73
|
+
install_cask 'backblaze' # Will require cleanup task to run installer.
|
74
|
+
install_brew 'git' # No further configuration required.
|
75
|
+
install_cask 'github' # Configuration will occur on first run of application.
|
76
|
+
install_cask 'google-chrome' # No further configuration required.
|
77
|
+
install_cask 'google-drive' # Configuration will occur on first run of application.
|
78
|
+
#install_cask 'macvim'
|
79
|
+
install_brew 'macvim', '--override-system-vim --with-python3'
|
80
|
+
install_file 'vimrc', '~/.vimrc'
|
81
|
+
install_cask 'screenhero' # Configuration will occur on first run of application.
|
82
|
+
install_cask 'textmate'
|
83
|
+
install_cask 'zoomus' # Configuration will occur on first run of applicaiton.
|
84
|
+
|
85
|
+
# Run BackBlaze Installer
|
86
|
+
cleanup << %q[run_cmd "open -a '/opt/homebrew-cask/Caskroom/backblaze/latest/Backblaze Installer.app'", "Installing BackBlaze."]
|
87
|
+
end # options[:groups] = default
|
88
|
+
|
89
|
+
if options[:groups].include? 'developer'
|
90
|
+
puts "### Starting installation of developer apps... ###"
|
91
|
+
install_cask '1password'
|
92
|
+
install_cask 'alfred'
|
93
|
+
install_cask 'anvil'
|
94
|
+
install_brew 'python'
|
95
|
+
install_brew 'python3'
|
96
|
+
install_brew 'cassandra'
|
97
|
+
run_cmd 'pip install cql &> /dev/null', 'Installing cql python module via pip...'
|
98
|
+
run_cmd 'pip3 install cql &> /dev/null', 'Installing cql python3 module via pip3...'
|
99
|
+
install_cask 'dash'
|
100
|
+
install_brew 'node'
|
101
|
+
install_brew 'nvm'
|
102
|
+
install_brew 'phantomjs'
|
103
|
+
install_brew 'homebrew/versions/postgresql92'
|
104
|
+
install_brew 'pow'
|
105
|
+
install_brew 'rbenv'
|
106
|
+
install_brew 'redis'
|
107
|
+
install_brew 'ruby-build'
|
108
|
+
install_cask 'slack'
|
109
|
+
install_cask 'tower'
|
110
|
+
# Configure nvm
|
111
|
+
mkdir '~/.nvm'
|
112
|
+
add_line_to_file '~/.zshrc', 'export NVM_DIR=~/.nvm'
|
113
|
+
add_line_to_file '~/.zshrc', 'source $(brew --prefix nvm)/nvm.sh'
|
114
|
+
# Configure pow
|
115
|
+
if not File.directory? File.expand_path('~/Library/Application Support/Pow/Hosts')
|
116
|
+
run_cmd 'mkdir -p ~/Library/Application\ Support/Pow/Hosts', 'Creating support directory for pow hosts...'
|
117
|
+
end
|
118
|
+
if not File.symlink? File.expand_path('~/.pow')
|
119
|
+
run_cmd 'ln -s ~/Library/Application\ Support/Pow/Hosts ~/.pow', 'Symlinking pow hosts directory to ~/.pow ...'
|
120
|
+
end
|
121
|
+
run_cmd 'sudo pow --install-system', 'Configuring port 80 forwarding for pow...'
|
122
|
+
run_cmd 'pow --install-local', 'Configuring launchd agent for pow...'
|
123
|
+
run_cmd 'sudo launchctl load -w /Library/LaunchDaemons/cx.pow.firewall.plist', 'Configuring pow launchd agent to start on boot...'
|
124
|
+
run_cmd 'launchctl load -w ~/Library/LaunchAgents/cx.pow.powd.plist', 'Starting pow...'
|
125
|
+
# Configure rbenv
|
126
|
+
system("grep -q -F 'export RBENV_ROOT=/usr/local/var/rbenv' /etc/profile")
|
127
|
+
if $? != 0
|
128
|
+
run_cmd "echo 'export RBENV_ROOT=/usr/local/var/rbenv' | sudo tee -a /etc/profile > /dev/null", "Adding RBENV_ROOT to /etc/profile..."
|
129
|
+
end
|
130
|
+
system("grep -q -F 'rbenv init -' /etc/profile")
|
131
|
+
if $? != 0
|
132
|
+
run_cmd %q[echo 'eval "$(rbenv init -)"' | sudo tee -a /etc/profile > /dev/null], "Adding rbenv init to /etc/profile..."
|
133
|
+
end
|
134
|
+
Dir.mkdir '/usr/local/var/rbenv/plugins' if not Dir.exists? '/usr/local/var/rbenv/plugins'
|
135
|
+
if File.exists? '/usr/local/var/rbenv/plugins/rbenv-gem-rehash'
|
136
|
+
puts 'rbenv-gem-rehash already installed...skipped.'
|
137
|
+
else
|
138
|
+
run_cmd 'sudo git clone https://github.com/sstephenson/rbenv-gem-rehash.git /usr/local/var/rbenv/plugins/rbenv-gem-rehash', "Installing rbenv-gem-rehash..."
|
139
|
+
end
|
140
|
+
# OH MY ZSH!
|
141
|
+
if not File.directory? File.expand_path('~/.oh-my-zsh')
|
142
|
+
run_cmd "curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh", "Installing oh-my-zsh..."
|
143
|
+
end
|
144
|
+
end # options[:groups] = developer
|
145
|
+
|
146
|
+
if not cleanup.empty?
|
147
|
+
cleanup.each do |cmd|
|
148
|
+
puts "(cleanup) #{cmd}"
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
2
|
+
" PLEASE DO NOT EDIT THIS FILE DIRECTLY.
|
3
|
+
" IF YOU NEED TO CUSTOMIZE, ADD TO ~/.vim.local
|
4
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
5
|
+
|
6
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
7
|
+
" Vundle
|
8
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
9
|
+
|
10
|
+
set nocompatible
|
11
|
+
filetype off
|
12
|
+
set rtp+=~/.vim/bundle/Vundle.vim
|
13
|
+
call vundle#begin()
|
14
|
+
Plugin 'gmarik/Vundle.vim'
|
15
|
+
Plugin 'scrooloose/nerdtree'
|
16
|
+
Plugin 'kien/ctrlp.vim'
|
17
|
+
Plugin 'altercation/vim-colors-solarized'
|
18
|
+
call vundle#end()
|
19
|
+
filetype plugin indent on
|
20
|
+
|
21
|
+
|
22
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
23
|
+
" Settings
|
24
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
25
|
+
|
26
|
+
let mapleader=","
|
27
|
+
|
28
|
+
"syntax highlighting
|
29
|
+
syntax on
|
30
|
+
|
31
|
+
"turn on line numbers
|
32
|
+
set number
|
33
|
+
|
34
|
+
"search options
|
35
|
+
set hlsearch
|
36
|
+
set incsearch
|
37
|
+
|
38
|
+
"Show command in bottom right portion of the screen
|
39
|
+
set showcmd
|
40
|
+
|
41
|
+
":e autocomplete settings
|
42
|
+
set wildmenu
|
43
|
+
set wildmode=longest:list,full
|
44
|
+
|
45
|
+
"format the statusline
|
46
|
+
set laststatus=2
|
47
|
+
|
48
|
+
"don't create swap files
|
49
|
+
set nobackup
|
50
|
+
set nowritebackup
|
51
|
+
set noswapfile
|
52
|
+
|
53
|
+
"tabbing
|
54
|
+
set tabstop=2
|
55
|
+
set shiftwidth=2
|
56
|
+
set expandtab
|
57
|
+
set autoindent
|
58
|
+
set smartindent
|
59
|
+
|
60
|
+
"backspace key
|
61
|
+
set backspace=2
|
62
|
+
|
63
|
+
"don't auto wrap lines
|
64
|
+
set tw=0
|
65
|
+
|
66
|
+
"auto load when file changed outside vim
|
67
|
+
set autoread
|
68
|
+
|
69
|
+
"auto save changes
|
70
|
+
set autowrite
|
71
|
+
set autowriteall
|
72
|
+
|
73
|
+
"ignores
|
74
|
+
set wildignore+=*tmp/*,*node_modules/*,*bower_components/*,*.git/*
|
75
|
+
|
76
|
+
"NERDTree settings
|
77
|
+
let NERDTreeShowHidden=1
|
78
|
+
|
79
|
+
|
80
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
81
|
+
" Style
|
82
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
83
|
+
|
84
|
+
"syntax highlighting
|
85
|
+
let g:solarized_termcolors=256
|
86
|
+
let g:solarized_termtrans=1
|
87
|
+
set background=dark
|
88
|
+
colorscheme solarized
|
89
|
+
|
90
|
+
"gvim options
|
91
|
+
if has("gui_running")
|
92
|
+
"remove scrollbars
|
93
|
+
set guioptions-=l
|
94
|
+
set guioptions-=L
|
95
|
+
set guioptions-=r
|
96
|
+
set guioptions-=b
|
97
|
+
endif
|
98
|
+
|
99
|
+
|
100
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
101
|
+
" Mappings
|
102
|
+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
103
|
+
|
104
|
+
"j and k shouldn't skip over wrapped lines
|
105
|
+
nnoremap j gj
|
106
|
+
nnoremap k gk
|
107
|
+
|
108
|
+
"NERDTree
|
109
|
+
nmap <silent> <Leader>e :NERDTreeToggle<CR>
|
110
|
+
|
111
|
+
"fuzzy file search
|
112
|
+
nmap <Leader>t <C-P>
|
113
|
+
|
114
|
+
if filereadable(expand("~/.vimrc.local"))
|
115
|
+
source ~/.vimrc.local
|
116
|
+
endif
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
require 'digest'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
def get_datadir
|
6
|
+
datadir = Gem.datadir('ahalogy-automation')
|
7
|
+
datadir = File.join(File.dirname(__FILE__), '../../data/ahalogy-automation') if datadir== nil
|
8
|
+
return datadir
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_cmd(cmd, msg)
|
12
|
+
puts msg
|
13
|
+
puts "(cmd) '#{cmd}'".colorize(:blue)
|
14
|
+
system cmd
|
15
|
+
abort 'FAILED.' if $? != 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def install_brew(app, opts = '')
|
19
|
+
%x[brew list #{app}]
|
20
|
+
if $? == 0
|
21
|
+
puts "(brew) #{app} already installed...skipped.".colorize(:green)
|
22
|
+
else
|
23
|
+
puts "(brew) install #{app} #{opts}".colorize(:blue)
|
24
|
+
system 'brew', 'install', app, opts
|
25
|
+
abort 'FAILED.' if $? != 0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def uninstall_brew(app)
|
30
|
+
%x[brew list #{app}]
|
31
|
+
if $? != 0
|
32
|
+
puts "(brew) #{app} is not installed...skipped.".colorize(:green)
|
33
|
+
else
|
34
|
+
puts "(brew-uninstall) uninstall #{app}".colorize(:blue)
|
35
|
+
system 'brew', 'uninstall', '--force', app
|
36
|
+
abort 'FAILED.' if $? != 0
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def install_cask(app)
|
41
|
+
%x[brew cask list #{app}]
|
42
|
+
if $? == 0
|
43
|
+
puts "(cask) #{app} already installed...skipped.".colorize(:green)
|
44
|
+
else
|
45
|
+
puts "(cask) install #{app}".colorize(:blue)
|
46
|
+
system 'brew', 'cask', 'install', app
|
47
|
+
abort 'FAILED.' if $? != 0
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def install_file(file, destination)
|
52
|
+
file = File.join(get_datadir, file)
|
53
|
+
if not File.readable? file
|
54
|
+
puts "(file) Attempted to install #{file} but the file was not found.".colorize(:red)
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
destination = File.expand_path(destination)
|
58
|
+
filemd5 = Digest::MD5.file(file).hexdigest
|
59
|
+
destmd5 = ''
|
60
|
+
if File.readable? destination
|
61
|
+
destmd5 = Digest::MD5.file(destination).hexdigest
|
62
|
+
end
|
63
|
+
if filemd5 == destmd5
|
64
|
+
puts "(file) #{file} and #{destination} are the same file...skipped.".colorize(:green)
|
65
|
+
else
|
66
|
+
puts "(file) Copying #{file} to #{destination}...".colorize(:blue)
|
67
|
+
FileUtils.cp file, destination
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_line_to_file(file, line, regex = nil)
|
72
|
+
regex = Regexp.escape(line) if regex == nil
|
73
|
+
run_cmd "grep '#{regex}' #{file} --quiet || echo '#{line}' >> #{file}", "Updating #{file}..."
|
74
|
+
end
|
75
|
+
|
76
|
+
def mkdir(dir)
|
77
|
+
dir = File.expand_path dir
|
78
|
+
if File.exists? dir
|
79
|
+
if File.directory? dir
|
80
|
+
puts "(mkdir) The directory #{dir} already exists...skipped.".colorize(:green)
|
81
|
+
else
|
82
|
+
fail "(mkdir) ERROR: Trying to create directory but file already exists at #{dir}".colorize(:red)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
puts "(mkdir) Creating directory #{dir}...".colorize(:blue)
|
86
|
+
FileUtils.mkdir dir
|
87
|
+
end
|
88
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ahalogy-automation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zan Loy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: github
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
executables:
|
44
|
+
- a5y-configure
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Rakefile
|
49
|
+
- ahalogy-automation.gemspec
|
50
|
+
- bin/a5y-configure
|
51
|
+
- data/ahalogy-automation/vimrc
|
52
|
+
- lib/ahalogy/install-helper.rb
|
53
|
+
homepage:
|
54
|
+
licenses: []
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.4.2
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Scripts to handle IT automation.
|
76
|
+
test_files: []
|