Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b48e997a4b | ||
|
|
3a45cdef4a | ||
|
|
bd3bf37643 | ||
|
|
e196d321c5 | ||
|
|
422da7043f | ||
|
|
1854d7116c | ||
|
|
c8cdbf38bf | ||
|
|
5f1afd89ee | ||
|
|
8ff4239a65 | ||
|
|
7ea6e10282 | ||
|
|
e97e900fc6 | ||
|
|
7e9ec37103 | ||
|
|
d9e74c2538 | ||
|
|
9124e93dca | ||
|
|
cd9ccec19c | ||
|
|
73af20ded7 | ||
|
|
f127f27ecd | ||
|
|
222eda3746 | ||
|
|
c38ad7e089 | ||
|
|
bc7cb9c355 | ||
|
|
96c533fc1a | ||
|
|
8c75cac48a | ||
|
|
cc20c7b205 | ||
|
|
50b266013b | ||
|
|
75747a8ee9 | ||
|
|
9fab1b2411 | ||
|
|
77f0d1f67b | ||
|
|
189c4c3856 | ||
|
|
59d652710a | ||
|
|
ea2f212787 | ||
|
|
f78be1cb56 | ||
|
|
0255655615 | ||
|
|
f1df4dcc69 | ||
|
|
4317cf9cd4 | ||
|
|
150736f4f4 | ||
|
|
d2784cc87b | ||
|
|
62f1f5d162 | ||
|
|
cfe75d2873 | ||
|
|
5f451a786f | ||
|
|
3b6a4f3fc4 | ||
|
|
879bb6f79e | ||
|
|
e733694f2d | ||
|
|
0ec287c977 | ||
|
|
833cef7527 | ||
|
|
28f555bcf3 | ||
|
|
363bdb1493 | ||
|
|
1373196eb5 | ||
|
|
da7b7191c9 | ||
|
|
1660acbcbb | ||
|
|
9c3790e438 | ||
|
|
f5c7e0b1a1 | ||
|
|
3039f75179 | ||
|
|
637d49e1ab | ||
|
|
ea4be19a86 | ||
|
|
befd01cb03 | ||
|
|
fdd0ff6532 | ||
|
|
074546bdda | ||
|
|
6a6e474a1e | ||
|
|
3eb0f22ef9 | ||
|
|
d68fdf8d5d | ||
|
|
2dc00dc2cd | ||
|
|
02e9ac6683 | ||
|
|
700d13876a | ||
|
|
a6f2c9fb07 | ||
|
|
407240e2a2 | ||
|
|
852f8551af |
+6
-12
@@ -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
|
||||||
|
|||||||
+5
-20
@@ -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}
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
+7
-9
@@ -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}'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 not isinstance(e, ProcFailure):
|
|
||||||
# no need to reraise in case of command error
|
|
||||||
# because the command has been printed
|
|
||||||
|
|
||||||
if reraise:
|
if reraise:
|
||||||
# nested call, re-raise
|
# nested call, re-raise
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exception(type(e), e, sys.exc_info()[2])
|
traceback.print_exception(type(e), e, sys.exc_info()[2])
|
||||||
|
return True
|
||||||
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
@@ -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,18 +149,7 @@ 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 = (
|
||||||
@@ -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
@@ -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',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
|
||||||
@@ -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())
|
|
||||||
Reference in New Issue
Block a user