66 Commits
Author SHA1 Message Date
jpic b48e997a4b Fixing push 2020-10-08 01:24:53 +02:00
jpic 3a45cdef4a Fix up cmd 2020-10-07 23:55:10 +02:00
jpic bd3bf37643 Target level cleaning had been forgotten
... when action level cleaning was added

Test both while we're at it, as this is pretty critical for actions to
clean up properly
2020-10-07 23:15:14 +02:00
jpic e196d321c5 Commenting docker job for now 2020-10-05 18:41:16 +02:00
jpic 422da7043f test 2020-10-05 18:38:03 +02:00
jpic 1854d7116c Fix shlax.cli (finally) 2020-10-05 18:30:00 +02:00
jpic c8cdbf38bf Cache invalidation failures must not stop build
Images may still be in use by running containers
2020-10-05 18:29:59 +02:00
jpic 5f1afd89ee Prevent print traceback for failed commands 2020-10-05 18:29:15 +02:00
jpic 8ff4239a65 Forward CLI arguments 2020-10-05 18:28:53 +02:00
jpic 7ea6e10282 Fix Pod.build to unshare prior to building async 2020-08-28 18:43:56 +02:00
jpic e97e900fc6 Add target argument only if present in sig 2020-08-28 18:39:16 +02:00
jpic 7e9ec37103 Readability 2020-08-28 18:38:11 +02:00
jpic d9e74c2538 Add container inspect 2020-08-28 18:37:25 +02:00
jpic 9124e93dca Layers refactor 2020-08-08 16:08:01 +02:00
jpic cd9ccec19c Support configured containers in start 2020-08-08 16:07:15 +02:00
jpic 73af20ded7 Fix TargetArgument implementation to stay optional 2020-08-08 15:54:02 +02:00
jpic f127f27ecd Add exec command 2020-08-02 22:19:13 +02:00
jpic 222eda3746 Skip report display for only one result 2020-08-02 20:11:24 +02:00
jpic c38ad7e089 Getting on par with docker-compose 2020-08-02 20:11:07 +02:00
jpic bc7cb9c355 Remove artificial centering from output labels 2020-08-02 20:10:19 +02:00
jpic 96c533fc1a Name parallel executor 2020-08-02 20:09:40 +02:00
jpic 8c75cac48a Add Buildah.Env and Buildah.Config 2020-08-02 06:52:39 +02:00
jpic cc20c7b205 New write with bash heredoc 2020-08-02 06:52:03 +02:00
jpic 50b266013b Let an action mark itself as skipped 2020-08-02 06:51:25 +02:00
jpic 75747a8ee9 Container: support not having a build job and new methods 2020-08-02 06:51:07 +02:00
jpic 9fab1b2411 Fix user action 2020-08-02 06:50:42 +02:00
jpic 77f0d1f67b Run(root) 2020-08-02 06:50:33 +02:00
jpic 189c4c3856 Test build-itself 2020-07-06 08:58:36 +02:00
jpic 59d652710a Update TargetArgument docs 2020-06-11 18:39:43 +02:00
jpic ea2f212787 Mention command line 2020-06-11 18:13:01 +02:00
jpic f78be1cb56 Fix title order 2020-06-11 18:12:02 +02:00
jpic 0255655615 Lolnote 2020-06-11 18:11:06 +02:00
jpic f1df4dcc69 Going to maintain a little news at the top of the README 2020-06-11 18:08:59 +02:00
jpic 4317cf9cd4 Do not try to commit a container that has not been created because layers are uptodate 2020-06-11 17:44:18 +02:00
150736f4f4 Merge branch 'mostadvanced' into 'master'
Mostadvanced

See merge request oss/shlax!4
2020-06-11 17:43:06 +02:00
jpic d2784cc87b Fixing container config support 2020-06-11 17:40:01 +02:00
jpic 62f1f5d162 Commiting build-itself job until i re-implement docker commiting 2020-06-11 17:37:09 +02:00
jpic cfe75d2873 Clean on KeyboardInterrupt, proper call in shlax Command 2020-06-11 03:51:28 +02:00
jpic 5f451a786f Package action working both on SSH host and Buildah guest now 2020-06-11 03:19:01 +02:00
jpic 3b6a4f3fc4 Added ssh target 2020-06-01 15:41:22 +02:00
jpic 879bb6f79e Silence pip output 2020-05-31 13:24:31 +02:00
jpic e733694f2d A bit of work on the command line 2020-05-31 13:22:36 +02:00
jpic 0ec287c977 Tag/build/push refactor 2020-05-31 12:53:57 +02:00
jpic 833cef7527 Typo in ci 2020-05-31 12:28:49 +02:00
jpic 28f555bcf3 Try more build 2020-05-31 12:23:48 +02:00
jpic 363bdb1493 Fix CI command to build 2020-05-31 05:15:15 +02:00
jpic 1373196eb5 Buildah __str__ 2020-05-31 03:51:13 +02:00
jpic da7b7191c9 Missing await in test function 2020-05-31 03:44:57 +02:00
jpic 1660acbcbb Pass status directly to clean 2020-05-31 03:44:51 +02:00
jpic 9c3790e438 Improve Buildah clean method 2020-05-31 03:40:00 +02:00
jpic f5c7e0b1a1 Set the action result prior to calling clean 2020-05-31 03:39:42 +02:00
jpic 3039f75179 Pip action implementation 2020-05-31 03:39:26 +02:00
jpic 637d49e1ab Bugfix: legacy code would prevent containers from shuting down after build 2020-05-31 02:45:24 +02:00
jpic ea4be19a86 Proper cache invalidation 2020-05-31 02:44:57 +02:00
jpic befd01cb03 Proper traceback prints 2020-05-31 02:44:13 +02:00
jpic fdd0ff6532 Copy action: refactor, caching, filtering 2020-05-31 02:43:37 +02:00
jpic 074546bdda Work on the CLI story 2020-05-31 00:10:57 +02:00
jpic 6a6e474a1e Adding Copy/User/Pip actions again 2020-05-31 00:00:25 +02:00
jpic 3eb0f22ef9 Add CLI to execute Actions on the fly 2020-05-31 00:00:25 +02:00
jpic d68fdf8d5d Proper render method actions 2020-05-31 00:00:25 +02:00
jpic 2dc00dc2cd fixup! Add layer caching 2020-05-31 00:00:25 +02:00
jpic 02e9ac6683 Replace Localhost with plain Target, ensure parent presence 2020-05-31 00:00:25 +02:00
jpic 700d13876a Add layer caching 2020-05-31 00:00:25 +02:00
jpic a6f2c9fb07 Add Proc.quiet 2020-05-31 00:00:25 +02:00
jpic 407240e2a2 Add Package.upgrade option 2020-05-31 00:00:25 +02:00
852f8551af Core rewrite
See merge request oss/shlax!2
2020-04-22 03:41:16 +02:00
17 changed files with 44 additions and 135 deletions
+6 -12
View File
@@ -1,27 +1,21 @@
build: build:
cache: cache:
key: cache key: cache
paths: [.cache, /var/lib/containers/] paths: [.cache]
image: yourlabs/buildah image: yourlabs/buildah
script: script:
- pip3 install -U --user .[cli] - pip3 install -U --user -e .[cli]
- CACHE_DIR=$(pwd)/.cache python3 ./shlaxfile.py build push=docker://docker.io/yourlabs/shlax:$CI_COMMIT_SHORT_SHA - CACHE_DIR=$(pwd)/.cache python3 ./shlaxfile.py build push
stage: build stage: build
build-itself: build-itself:
cache: cache:
key: cache key: cache
paths: [.cache, /var/lib/containers/] paths: [.cache]
image: yourlabs/shlax:$CI_COMMIT_SHORT_SHA image: quay.io/yourlabs/shlax:$CI_COMMIT_SHORT_SHA
script: python3 ./shlaxfile.py build push=docker://docker.io/yourlabs/shlax:$CI_COMMIT_REF script: python3 ./shlaxfile.py build
stage: test stage: test
test-exitcode:
image: yourlabs/shlax:$CI_COMMIT_SHORT_SHA
script:
- tests/shlaxfail.py build || [ $? -eq 1 ]
- tests/shlaxsuccess.py build
test: test:
image: yourlabs/python image: yourlabs/python
stage: build stage: build
View File
View File
+5 -20
View File
@@ -1,32 +1,19 @@
import asyncio import asyncio
import binascii import binascii
import glob
import os import os
from ..exceptions import ShlaxException
class Copy: class Copy:
def __init__(self, *args): def __init__(self, *args):
self.src = args[:-1]
self.dst = args[-1] self.dst = args[-1]
self.src = []
for src in args[:-1]: def listfiles(self):
if '*' in src:
self.src += glob.glob(src)
else:
self.src.append(src)
async def listfiles(self, target):
if getattr(self, '_listfiles', None): if getattr(self, '_listfiles', None):
return self._listfiles return self._listfiles
result = [] result = []
for src in self.src: for src in self.src:
if not await target.parent.exists(src):
target.output.fail(self)
raise ShlaxException(f'File not found {src}')
if os.path.isfile(src): if os.path.isfile(src):
result.append(src) result.append(src)
continue continue
@@ -45,7 +32,7 @@ class Copy:
async def __call__(self, target): async def __call__(self, target):
await target.mkdir(self.dst) await target.mkdir(self.dst)
for path in await self.listfiles(target): for path in self.listfiles():
if os.path.isdir(path): if os.path.isdir(path):
await target.mkdir(os.path.join(self.dst, path)) await target.mkdir(os.path.join(self.dst, path))
elif '/' in path: elif '/' in path:
@@ -61,11 +48,9 @@ class Copy:
def __str__(self): def __str__(self):
return f'Copy({", ".join(self.src)}, {self.dst})' return f'Copy({", ".join(self.src)}, {self.dst})'
async def cachekey(self, target): async def cachekey(self):
async def chksum(path): async def chksum(path):
with open(path, 'rb') as f: with open(path, 'rb') as f:
return (path, str(binascii.crc32(f.read()))) return (path, str(binascii.crc32(f.read())))
results = await asyncio.gather( results = await asyncio.gather(*[chksum(f) for f in self.listfiles()])
*[chksum(f) for f in await self.listfiles(target)]
)
return {path: chks for path, chks in results} return {path: chks for path, chks in results}
-11
View File
@@ -27,33 +27,28 @@ class Packages:
update='apk update', update='apk update',
upgrade='apk upgrade', upgrade='apk upgrade',
install='apk add', install='apk add',
host=None,
), ),
apt=dict( apt=dict(
update='apt-get -y update', update='apt-get -y update',
upgrade='apt-get -y upgrade', upgrade='apt-get -y upgrade',
install='apt-get -y --no-install-recommends install', install='apt-get -y --no-install-recommends install',
host=None,
), ),
pacman=dict( pacman=dict(
update='pacman -Sy', update='pacman -Sy',
upgrade='pacman -Su --noconfirm', upgrade='pacman -Su --noconfirm',
install='pacman -S --noconfirm', install='pacman -S --noconfirm',
lastupdate='stat -c %Y /var/lib/pacman/sync/core.db', lastupdate='stat -c %Y /var/lib/pacman/sync/core.db',
host='/var/lib/pacman',
), ),
dnf=dict( dnf=dict(
update='dnf makecache --assumeyes', update='dnf makecache --assumeyes',
upgrade='dnf upgrade --best --assumeyes --skip-broken', # noqa upgrade='dnf upgrade --best --assumeyes --skip-broken', # noqa
install='dnf install --setopt=install_weak_deps=False --best --assumeyes', # noqa install='dnf install --setopt=install_weak_deps=False --best --assumeyes', # noqa
lastupdate='stat -c %Y /var/cache/dnf/* | head -n1', lastupdate='stat -c %Y /var/cache/dnf/* | head -n1',
host=None,
), ),
yum=dict( yum=dict(
update='yum update', update='yum update',
upgrade='yum upgrade', upgrade='yum upgrade',
install='yum install', install='yum install',
host=None,
), ),
) )
@@ -67,12 +62,6 @@ class Packages:
self.packages += line.split(' ') self.packages += line.split(' ')
async def cache_setup(self, target): async def cache_setup(self, target):
# Try to use the host cache directory if present rather than home
# directory, in cases where host and guest are the same distros
hostpath = self.mgrs[self.mgr]['host']
if target.exists(hostpath):
self.cache_root = hostpath
if 'CACHE_DIR' in os.environ: if 'CACHE_DIR' in os.environ:
self.cache_root = os.path.join(os.getenv('CACHE_DIR')) self.cache_root = os.path.join(os.getenv('CACHE_DIR'))
else: else:
+3 -8
View File
@@ -13,7 +13,7 @@ import importlib
import os import os
import sys import sys
from .exceptions import ShlaxException from .proc import ProcFailure
class Group(cli2.Group): class Group(cli2.Group):
@@ -57,15 +57,10 @@ class Command(cli2.Command):
try: try:
result = super().__call__(*argv) result = super().__call__(*argv)
except ShlaxException as exc: except ProcFailure:
# just output the failure without TB, as command was already # just output the failure without TB, as command was already
# printed anyway # printed anyway
self.exit_code = 1 pass
self['target'].value.output.fail(exc)
if self['target'].value.results:
if self['target'].value.results[-1].status == 'failure':
self.exit_code = 1
self['target'].value.output.results(self['target'].value) self['target'].value.output.results(self['target'].value)
return result return result
View File
+7 -9
View File
@@ -60,11 +60,9 @@ class Image:
setattr(self, k, v) setattr(self, k, v)
# docker.io currently has issues with oci format # docker.io currently has issues with oci format
self.format = format or 'oci'
if self.registry == 'docker.io': if self.registry == 'docker.io':
self.backend = 'docker' self.format = 'docker'
if not self.format:
self.format = 'docker' if self.backend == 'docker' else 'oci'
# filter out tags which resolved to None # filter out tags which resolved to None
self.tags = [t for t in self.tags if t] self.tags = [t for t in self.tags if t]
@@ -76,19 +74,19 @@ class Image:
def __str__(self): def __str__(self):
return f'{self.repository}:{self.tags[-1]}' return f'{self.repository}:{self.tags[-1]}'
async def push(self, target, name=None): async def push(self, target):
user = os.getenv('IMAGES_USER', os.getenv('DOCKER_USER')) user = os.getenv('IMAGES_USER')
passwd = os.getenv('IMAGES_PASS', os.getenv('DOCKER_PASS')) passwd = os.getenv('IMAGES_PASS')
if user and passwd: if user and passwd:
target.output.cmd('buildah login -u ... -p ...' + self.registry) target.output.cmd('buildah login -u ... -p ...' + self.registry)
await target.parent.exec( await target.parent.exec(
'buildah', 'login', '-u', user, '-p', passwd, 'buildah', 'login', '-u', user, '-p', passwd,
self.registry or 'docker.io', quiet=True) self.registry or 'docker.io', debug=False)
for tag in self.tags: for tag in self.tags:
await target.parent.exec( await target.parent.exec(
'buildah', 'buildah',
'push', 'push',
self.repository + ':final', self.repository + ':final',
name if isinstance(name, str) else f'{self.registry}/{self.repository}:{tag}' f'{self.registry}/{self.repository}:{tag}'
) )
+1 -5
View File
@@ -101,11 +101,7 @@ class Output:
) )
def highlight(self, line, highlight=True): def highlight(self, line, highlight=True):
try: line = line.decode('utf8') if isinstance(line, bytes) else line
line = line.decode('utf8') if isinstance(line, bytes) else line
except UnicodeDecodeError:
highlight = False
if not highlight or ( if not highlight or (
'\x1b[' in line '\x1b[' in line
or '\033[' in line or '\033[' in line
+1 -2
View File
@@ -7,11 +7,10 @@ import os
import shlex import shlex
import sys import sys
from .exceptions import ShlaxException
from .output import Output from .output import Output
class ProcFailure(ShlaxException): class ProcFailure(Exception):
def __init__(self, proc): def __init__(self, proc):
self.proc = proc self.proc = proc
View File
View File
+8 -14
View File
@@ -6,7 +6,7 @@ import re
import sys import sys
from ..output import Output from ..output import Output
from ..proc import Proc, ProcFailure from ..proc import Proc
from ..result import Result, Results from ..result import Result, Results
@@ -68,19 +68,13 @@ class Target:
self.output.fail(action, e) self.output.fail(action, e)
result.status = 'failure' result.status = 'failure'
result.exception = e result.exception = e
if reraise:
if not isinstance(e, ProcFailure): # nested call, re-raise
# no need to reraise in case of command error raise
# because the command has been printed else:
import traceback
if reraise: traceback.print_exception(type(e), e, sys.exc_info()[2])
# nested call, re-raise return True
raise
else:
import traceback
traceback.print_exception(type(e), e, sys.exc_info()[2])
return True # because it failed
else: else:
if getattr(action, 'skipped', False): if getattr(action, 'skipped', False):
self.output.skip(action) self.output.skip(action)
+10 -16
View File
@@ -37,7 +37,7 @@ class Buildah(Target):
return 'Replacing with: buildah unshare ' + ' '.join(sys.argv) return 'Replacing with: buildah unshare ' + ' '.join(sys.argv)
return f'Buildah({self.image})' return f'Buildah({self.image})'
async def __call__(self, *actions, target=None, push: str=False): async def __call__(self, *actions, target=None, push: bool=False):
if target: if target:
self.parent = target self.parent = target
@@ -57,8 +57,12 @@ class Buildah(Target):
if actions: if actions:
actions = actions[len(keep):] actions = actions[len(keep):]
if not actions:
return self.output.success('Image up to date')
else: else:
self.actions = self.actions[len(keep):] self.actions = self.actions[len(keep):]
if not self.actions:
return self.output.success('Image up to date')
self.ctr = (await self.parent.exec('buildah', 'from', self.base)).out self.ctr = (await self.parent.exec('buildah', 'from', self.base)).out
self.root = Path((await self.parent.exec('buildah', 'mount', self.ctr)).out) self.root = Path((await self.parent.exec('buildah', 'mount', self.ctr)).out)
@@ -88,7 +92,7 @@ class Buildah(Target):
prefix = tag prefix = tag
break break
if hasattr(action, 'cachekey'): if hasattr(action, 'cachekey'):
action_key = action.cachekey(self) action_key = action.cachekey()
if asyncio.iscoroutine(action_key): if asyncio.iscoroutine(action_key):
action_key = str(await action_key) action_key = str(await action_key)
else: else:
@@ -107,6 +111,7 @@ class Buildah(Target):
await self.parent.exec( await self.parent.exec(
'buildah', 'buildah',
'commit', 'commit',
'--format=' + action_image.format,
self.ctr, self.ctr,
action_image, action_image,
) )
@@ -122,7 +127,7 @@ class Buildah(Target):
if result.status == 'success' and self.ctr: if result.status == 'success' and self.ctr:
await self.commit() await self.commit()
if self.push: if self.push:
await self.image.push(target, self.push) await self.image.push(target)
if self.ctr is not None: if self.ctr is not None:
await self.parent.exec('buildah', 'rm', self.ctr) await self.parent.exec('buildah', 'rm', self.ctr)
@@ -144,19 +149,8 @@ class Buildah(Target):
async def commit(self): async def commit(self):
await self.parent.exec( await self.parent.exec(
'buildah', f'buildah commit {self.ctr} {self.image.repository}:final'
'commit',
f'--format={self.image.format}',
self.ctr,
f'{self.image.repository}:final',
) )
if self.image.backend == 'docker':
await self.parent.exec(
'buildah',
'push',
f'{self.image.repository}:final',
f'docker-daemon:{self.image.repository}:latest'
)
ENV_TAGS = ( ENV_TAGS = (
# gitlab # gitlab
@@ -187,7 +181,7 @@ class Buildah(Target):
return await self.parent.mkdir(*[self.path(path) for path in paths]) return await self.parent.mkdir(*[self.path(path) for path in paths])
async def copy(self, *args): async def copy(self, *args):
return await self.parent.exec('buildah', 'copy', self.ctr, *args) return await self.parent.copy(*args[:-1], self.path(args[-1]))
async def write(self, path, content): async def write(self, path, content):
return await self.write(path, content) return await self.write(path, content)
+3 -3
View File
@@ -9,9 +9,9 @@ shlax = Container(
build=Buildah( build=Buildah(
Packages('python38', 'buildah', 'unzip', 'findutils', upgrade=False), Packages('python38', 'buildah', 'unzip', 'findutils', upgrade=False),
Copy('setup.py', 'shlax', '/app'), Copy('setup.py', 'shlax', '/app'),
Pip('/app[cli]'), Pip('/app'),
base='quay.io/buildah/stable', base='quay.io/podman/stable',
commit='docker://docker.io/yourlabs/shlax', commit='quay.io/yourlabs/shlax',
), ),
) )
-18
View File
@@ -1,18 +0,0 @@
#!/usr/bin/env python
"""
Shlaxfile for shlax itself.
"""
from shlax.shortcuts import *
shlax = Container(
build=Buildah(
Packages('prout', upgrade=False),
base='alpine',
commit='shlaxfail',
),
)
if __name__ == '__main__':
print(Group(doc=__doc__).load(shlax).entry_point())
-17
View File
@@ -1,17 +0,0 @@
#!/usr/bin/env python
"""
Shlaxfile for shlax itself.
"""
from shlax.shortcuts import *
shlax = Container(
build=Buildah(
base='alpine',
commit='shlaxsuccess',
),
)
if __name__ == '__main__':
print(Group(doc=__doc__).load(shlax).entry_point())