@@ -37,38 +37,27 @@ def is_podman(runner):
3737 return True
3838 return False
3939
40- def main ():
41- """ Main entry point. """
42- parser = argparse .ArgumentParser ()
40+ def add_common_args (parser ):
4341 parser .add_argument ('-b' , '--branch' ,
4442 help = 'XCP-ng version: 7.6, %s, etc. If not set, '
4543 'will default to %s.' % (DEFAULT_BRANCH , DEFAULT_BRANCH ))
46- parser .add_argument ('-l' , '--build-local' ,
47- help = "Install dependencies for the spec file(s) found in the SPECS/ subdirectory "
48- "of the directory passed as parameter, then build the RPM(s). "
49- "Built RPMs and SRPMs will be in RPMS/ and SRPMS/ subdirectories. "
50- "Any preexisting BUILD, BUILDROOT, RPMS or SRPMS directories will be removed first. "
51- "If --output-dir is set, the RPMS and SRPMS directories will be copied to it "
52- "after the build." )
53- parser .add_argument ('--define' ,
54- help = "Definitions to be passed to rpmbuild (if --build-local is "
55- "passed too). Example: --define 'xcp_ng_section extras', for building the 'extras' "
56- "version of a package which exists in both 'base' and 'extras' versions." )
57- parser .add_argument ('--rpmbuild-opts' , action = 'append' ,
58- help = "Pass additional option(s) to rpmbuild" )
59- parser .add_argument ('--rpmbuild-stage' , action = 'store' ,
60- help = f"Request given -bX stage rpmbuild, X in [{ RPMBUILD_STAGES } ]" )
61- parser .add_argument ('-o' , '--output-dir' ,
62- help = "Output directory for --build-local." )
6344 parser .add_argument ('-n' , '--no-exit' , action = 'store_true' ,
64- help = 'After executing either an automated build or a custom command passed as parameter, '
65- 'drop user into a shell' )
45+ help = 'After finishing the execution of the action, drop user into a shell' )
6646 parser .add_argument ('-d' , '--dir' , action = 'append' ,
6747 help = 'Local dir to mount in the '
6848 'image. Will be mounted at /external/<dirname>' )
6949 parser .add_argument ('-e' , '--env' , action = 'append' ,
7050 help = 'Environment variables passed directly to '
7151 f'{ RUNNER } -e' )
52+ parser .add_argument ('-a' , '--enablerepo' ,
53+ help = 'additional repositories to enable before installing build dependencies. '
54+ 'Same syntax as yum\' s --enablerepo parameter. Available additional repositories: '
55+ 'check files/xcp-ng.repo.*.x.in.' )
56+ parser .add_argument ('--disablerepo' ,
57+ help = 'disable repositories. Same syntax as yum\' s --disablerepo parameter. '
58+ 'If both --enablerepo and --disablerepo are set, --disablerepo will be applied first' )
59+
60+ def add_container_args (parser ):
7261 parser .add_argument ('-v' , '--volume' , action = 'append' ,
7362 help = f'Volume mounts passed directly to { RUNNER } -v' )
7463 parser .add_argument ('--rm' , action = 'store_true' ,
@@ -78,26 +67,78 @@ def main():
7867 parser .add_argument ('--name' , help = 'Assign a name to the container' )
7968 parser .add_argument ('--ulimit' , action = 'append' ,
8069 help = f'Ulimit options passed directly to { RUNNER } run' )
81- parser .add_argument ('-a' , '--enablerepo' ,
82- help = 'additional repositories to enable before installing build dependencies. '
83- 'Same syntax as yum\' s --enablerepo parameter. Available additional repositories: '
84- 'check files/xcp-ng.repo.*.x.in.' )
85- parser .add_argument ('--disablerepo' ,
86- help = 'disable repositories. Same syntax as yum\' s --disablerepo parameter. '
87- 'If both --enablerepo and --disablerepo are set, --disablerepo will be applied first' )
8870 parser .add_argument ('--platform' , action = 'store' ,
8971 help = "Override the default platform for the build container. "
9072 "Can notably be used to workaround podman bug #6185 fixed in v5.5.1." )
9173 parser .add_argument ('--fail-on-error' , action = 'store_true' ,
9274 help = 'If container initialisation fails, exit rather than dropping the user '
93- 'into a command shell' )
75+ 'into a shell' )
9476 parser .add_argument ('--debug' , action = 'store_true' ,
9577 help = 'Enable script tracing in container initialization (sh -x)' )
96- parser .add_argument ('command' , nargs = argparse .REMAINDER ,
97- help = 'Command to run inside the prepared container' )
9878
99- args = parser .parse_args (sys .argv [1 :])
10079
80+ def buildparser ():
81+ parser = argparse .ArgumentParser ()
82+ subparsers_env = parser .add_subparsers (
83+ required = True , title = "Development environments" ,
84+ help = "Available environments" )
85+
86+ # container-based workflow
87+ parser_container = subparsers_env .add_parser ('container' , help = "Use a local container to build a package" )
88+ parser_container .set_defaults (func = container )
89+ subparsers_container = parser_container .add_subparsers (
90+ dest = 'action' , required = True ,
91+ help = "Actions available for developing packages" )
92+
93+ # build -- build an rpm using a container
94+ parser_build = subparsers_container .add_parser (
95+ 'build' ,
96+ help = "Install dependencies for the spec file(s) found in the SPECS/ subdirectory "
97+ "of the directory passed as parameter, then build the RPM(s). "
98+ "Built RPMs and SRPMs will be in RPMS/ and SRPMS/ subdirectories. "
99+ "Any preexisting BUILD, BUILDROOT, RPMS or SRPMS directories will be removed first." )
100+ parser_build .add_argument ('build_local' ,
101+ help = "Root path where SPECS/ and SOURCES are available" )
102+ parser_build .add_argument (
103+ '--define' ,
104+ help = "Definitions to be passed to rpmbuild. Example: --define "
105+ "'xcp_ng_section extras', for building the 'extras' "
106+ "version of a package which exists in both 'base' and 'extras' versions." )
107+ parser_build .add_argument (
108+ '-o' , '--output-dir' ,
109+ help = "Directory where the RPMs, SRPMs and the build logs will appear. "
110+ "The directory is created if it doesn't exist" )
111+ parser_build .add_argument (
112+ '--rpmbuild-opts' , action = 'append' ,
113+ help = "Pass additional option(s) to rpmbuild" )
114+ parser_build .add_argument (
115+ '--rpmbuild-stage' , action = 'store' ,
116+ help = f"Request given -bX stage rpmbuild, X in [{ RPMBUILD_STAGES } ]" )
117+ add_container_args (parser_build )
118+ add_common_args (parser_build )
119+
120+ # run -- execute commands inside a container
121+ parser_run = subparsers_container .add_parser (
122+ 'run' ,
123+ help = 'Execute a command inside a container' )
124+ parser_run .add_argument (
125+ 'command' , nargs = argparse .REMAINDER ,
126+ help = 'Command to run inside the prepared container' )
127+ add_container_args (parser_run )
128+ add_common_args (parser_run )
129+
130+ # shell -- like run bash
131+ parser_shell = argparse .ArgumentParser ()
132+ parser_shell = subparsers_container .add_parser (
133+ 'shell' ,
134+ help = 'Drop a shell into the prepared container' )
135+ add_container_args (parser_shell )
136+ add_common_args (parser_shell )
137+
138+ return parser
139+
140+ def container (args ):
141+ build = args .action == 'build'
101142 branch = args .branch or DEFAULT_BRANCH
102143 docker_arch = args .platform or ("linux/amd64/v2" if branch == "9.0" else "linux/amd64" )
103144
@@ -110,24 +151,24 @@ def main():
110151 if args .rm :
111152 docker_args += ["--rm=true" ]
112153
113- if args .command != []:
154+ if hasattr ( args , 'command' ) and args .command != []:
114155 docker_args += ["-e" , "COMMAND=%s" % ' ' .join (args .command )]
115- if args . build_local :
156+ if build :
116157 docker_args += ["-v" , "%s:/home/builder/rpmbuild" %
117158 os .path .abspath (args .build_local )]
118159 docker_args += ["-e" , "BUILD_LOCAL=1" ]
119- if args .define :
160+ if hasattr ( args , 'define' ) and args .define :
120161 docker_args += ["-e" , "RPMBUILD_DEFINE=%s" % args .define ]
121- if args .rpmbuild_opts :
162+ if hasattr ( args , 'rpmbuild_opts' ) and args .rpmbuild_opts :
122163 docker_args += ["-e" , "RPMBUILD_OPTS=%s" % ' ' .join (args .rpmbuild_opts )]
123- if args .rpmbuild_stage :
164+ if hasattr ( args , 'rpmbuild_stage' ) and args .rpmbuild_stage :
124165 if args .rpmbuild_stage not in RPMBUILD_STAGES :
125166 parser .error (f"--rpmbuild-stage={ args .rpmbuild_stage } not in '{ RPMBUILD_STAGES } '" )
126167 docker_args += ["-e" , f"RPMBUILD_STAGE={ args .rpmbuild_stage } " ]
127- if args .output_dir :
168+ if hasattr ( args , 'output_dir' ) and args .output_dir :
128169 if not os .path .isdir (args .output_dir ):
129- parser . error ( "%s is not a valid output directory." %
130- args . output_dir )
170+ print ( f" { args . output_dir } is not a valid output directory.")
171+ sys . exit ( 1 )
131172 docker_args += ["-v" , "%s:/home/builder/output" %
132173 os .path .abspath (args .output_dir )]
133174 if args .no_exit :
@@ -171,7 +212,15 @@ def main():
171212 docker_args += ["%s:%s" % (CONTAINER_PREFIX , branch ),
172213 "/usr/local/bin/init-container.sh" ]
173214 print ("Launching docker with args %s" % docker_args , file = sys .stderr )
174- return_code = subprocess .call (docker_args )
215+ return subprocess .call (docker_args )
216+
217+ def main ():
218+ """ Main entry point. """
219+ parser = buildparser ()
220+
221+ args = parser .parse_args ()
222+
223+ return_code = args .func (args )
175224
176225 sys .exit (return_code )
177226
0 commit comments