def set_default_track(snap_name: str, track_name: str): """Set the default track for <snap-name> to <track>. The track must be a valid active track for this operation to be successful. """ store_client_cli = StoreClientCLI() # Client-side check to verify that the selected track exists. snap_channel_map = store_client_cli.get_snap_channel_map(snap_name=snap_name) active_tracks = [ track.name for track in snap_channel_map.snap.tracks if track.status in ("default", "active") ] if track_name not in active_tracks: echo.exit_error( brief=f"The specified track {track_name!r} does not exist for {snap_name!r}.", resolution=f"Ensure the {track_name!r} track exists for the {snap_name!r} snap and try again.", details="Valid tracks for {!r}: {}.".format( snap_name, ", ".join([f"{t!r}" for t in active_tracks]) ), ) metadata = dict(default_track=track_name) store_client_cli.upload_metadata(snap_name=snap_name, metadata=metadata, force=True) echo.info(f"Default track for {snap_name!r} set to {track_name!r}.")
def upload(snap_file, release): """Upload <snap-file> to the store. By passing --release with a comma separated list of channels the snap would be released to the selected channels if the store review passes for this <snap-file>. This operation will block until the store finishes processing this <snap-file>. If --release is used, the channel map will be displayed after the operation takes place. \b Examples: snapcraft upload my-snap_0.1_amd64.snap snapcraft upload my-snap_0.2_amd64.snap --release edge snapcraft upload my-snap_0.3_amd64.snap --release candidate,beta """ click.echo("Preparing to upload {!r}.".format(os.path.basename(snap_file))) if release: channel_list = release.split(",") click.echo( "After uploading, the resulting snap revision will be released to " "{} when it passes the Snap Store review." "".format(formatting_utils.humanize_list(channel_list, "and")) ) else: channel_list = None review_snap(snap_file=snap_file) snap_name, snap_revision = snapcraft.upload(snap_file, channel_list) echo.info("Revision {!r} of {!r} created.".format(snap_revision, snap_name)) if channel_list: store_client_cli = StoreClientCLI() snap_channel_map = store_client_cli.get_snap_channel_map(snap_name=snap_name) click.echo( get_tabulated_channel_map( snap_channel_map, architectures=snap_channel_map.get_revision( snap_revision ).architectures, ) )
def list_tracks(snap_name: str) -> None: """List channel tracks for <snap-name>. This command has an alias of `tracks`. Track status, creation dates and version patterns are returned alongside the track names in a space formatted table. Possible Status values are: \b - active, visible tracks available for installation - default, the default track to install from when not explicit - hidden, tracks available for installation but unlisted - closed, tracks that are no longer available to install from A version pattern is a regular expression that restricts a snap revision from being released to a track if the version string set does not match. """ store_client_cli = StoreClientCLI() snap_channel_map = store_client_cli.get_snap_channel_map(snap_name=snap_name) # Iterate over the entries, replace None with - for consistent presentation track_table: List[List[str]] = [ [ track.name, track.status, track.creation_date if track.creation_date else "-", track.version_pattern if track.version_pattern else "-", ] for track in snap_channel_map.snap.tracks ] click.echo( tabulate( # Sort by "creation-date". sorted(track_table, key=operator.itemgetter(2)), headers=["Name", "Status", "Creation-Date", "Version-Pattern"], tablefmt="plain", ) )
def release( snap_name, revision, channels, progressive: Optional[int], experimental_progressive_releases: bool, ) -> None: """Release <snap-name> on <revision> to the selected store <channels>. <channels> is a comma separated list of valid channels on the store. The <revision> must exist on the store, to see available revisions run `snapcraft list-revisions <snap_name>`. The channel map will be displayed after the operation takes place. To see the status map at any other time run `snapcraft status <snap-name>`. The format for channels is `[<track>/]<risk>[/<branch>]` where \b - <track> is used to have long term release channels. It is implicitly set to `latest`. If this snap requires one, it can be created by request by having a conversation on https://forum.snapcraft.io under the *store* category. - <risk> is mandatory and can be either `stable`, `candidate`, `beta` or `edge`. - <branch> is optional and dynamically creates a channel with a specific expiration date. \b Examples: snapcraft release my-snap 8 stable snapcraft release my-snap 8 stable/my-branch snapcraft release my-snap 9 beta,edge snapcraft release my-snap 9 lts-channel/stable snapcraft release my-snap 9 lts-channel/stable/my-branch """ # If progressive is set to 100, treat it as None. if progressive == 100: progressive = None if progressive is not None and not experimental_progressive_releases: raise click.UsageError( "--progressive requires --experimental-progressive-releases." ) elif progressive: os.environ["SNAPCRAFT_EXPERIMENTAL_PROGRESSIVE_RELEASES"] = "Y" echo.warning("*EXPERIMENTAL* progressive releases in use.") store_client_cli = StoreClientCLI() release_data = store_client_cli.release( snap_name=snap_name, revision=revision, channels=channels.split(","), progressive_percentage=progressive, ) snap_channel_map = store_client_cli.get_snap_channel_map(snap_name=snap_name) architectures_for_revision = snap_channel_map.get_revision( int(revision) ).architectures tracks = [storeapi.channels.Channel(c).track for c in channels.split(",")] click.echo( get_tabulated_channel_map( snap_channel_map, tracks=tracks, architectures=architectures_for_revision ) ) opened_channels = release_data.get("opened_channels", []) if len(opened_channels) == 1: echo.info(f"The {opened_channels[0]!r} channel is now open.") elif len(opened_channels) > 1: channels = ("{!r}".format(channel) for channel in opened_channels[:-1]) echo.info( "The {} and {!r} channels are now open.".format( ", ".join(channels), opened_channels[-1] ) )