-
Notifications
You must be signed in to change notification settings - Fork 263
Add cli option to publish to core db. #744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
32c3409
155f164
c460517
655b56e
0327190
a0c6922
277cc0f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,15 +5,18 @@ | |
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import argparse | ||
import json | ||
import os | ||
import pathlib | ||
import shutil | ||
import signal | ||
import subprocess | ||
import sys | ||
import warnings | ||
from pathlib import Path | ||
|
||
import argcomplete | ||
import requests | ||
|
||
from fusesoc import signature | ||
|
||
|
@@ -298,6 +301,127 @@ def core_sign(fs, args): | |
print(f"{sigfile} created") | ||
|
||
|
||
def guess_provider(): | ||
guess = {"found": False} | ||
cmd = ["git", "remote", "-v"] | ||
res = subprocess.run(cmd, capture_output=True).stdout.decode("utf-8").strip() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's run this from the root directory of the core instead. We can pick up the directory from |
||
lines = res.splitlines() | ||
if len(lines) < 1: | ||
return guess | ||
fetchlines = list(filter(lambda s: s.endswith("(fetch)"), lines)) | ||
if len(fetchlines) < 1: | ||
return guess | ||
comps = fetchlines[0].split("/") | ||
if comps[2] == "github.com": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fails when there are more than one remote, e g.
In this particular case we might detect this situation and query the user, but my gut feeling tells me that there might be several more cases like this, so I think it would be good to have CLI options to manually specify at least the upstream URI |
||
guess["name"] = "github" | ||
else: | ||
guess["name"] = comps[2] | ||
user = comps[3] | ||
repo = comps[4] | ||
repo = repo[: len(repo) - len("(fetch)")].strip() | ||
cmd = ["git", "log", "-n", "1"] | ||
res = ( | ||
subprocess.run(cmd, capture_output=True) | ||
.stdout.decode("utf-8") | ||
.strip() | ||
.splitlines()[0] | ||
) | ||
comps = res.split(" ") | ||
if (len(comps) >= 2) and (comps[0] == "commit"): | ||
version = comps[1] | ||
else: | ||
version = "" | ||
guess[ | ||
"yaml" | ||
] = """provider: | ||
name : {} | ||
user : {} | ||
repo : {} | ||
version : {} | ||
""".format( | ||
guess["name"], user, repo, version | ||
) | ||
guess["found"] = True | ||
return guess | ||
|
||
|
||
def core_publish(fs, args): | ||
core = _get_core(fs, args.core) | ||
uri = fs.config.publish_uri | ||
pem = fs.config.publish_uri_pem | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean specifically the pem option? It was needed during development since that server was self signed, and why not keep the option? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allowing HTTPS connections with self-signed certificates - or even HTTP connections - could be a useful feature for local deployments or testing of the FuseSoC Package Directory Server. |
||
sigfile = core.core_file + ".sig" | ||
if (core.provider != None) and (core.provider.name != "github"): | ||
print( | ||
'The provider for this core is "' | ||
+ core.provider.name | ||
+ '" and only "github" is supported for publishing. Aborting.' | ||
) | ||
return False | ||
if core.provider == None: | ||
provider_info = guess_provider() | ||
if provider_info["found"] == False: | ||
print( | ||
"No provider is given in core file or guessable from current project, and a provider of type github is needed for publishing. Aborting." | ||
) | ||
return False | ||
if provider_info["name"] != "github": | ||
print( | ||
"No provider is given in core file, and the current project appears to not be on github, which is needed for publishing. Aborting." | ||
) | ||
return False | ||
print( | ||
"No provider is given in core file, but the current project seems to be on github." | ||
) | ||
if not args.autoprovider: | ||
print( | ||
"The following provider section can be added to the core file if the --autoprovider flag is given to this command." | ||
) | ||
print(provider_info["yaml"]) | ||
return False | ||
print("Adding the following provider section to the core file.") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We want to avoid adding the provider section to the .core file in the repo. Let's copy the core file to a temporary file instead where we can add the section and publish |
||
print(provider_info["yaml"]) | ||
cf = open(core.core_file, "ab") | ||
cf.write(("\n" + provider_info["yaml"] + "\n").encode("utf-8")) | ||
cf.close() | ||
print("Now retry publishing.") | ||
return False | ||
|
||
print("Core provider: " + core.provider.name) | ||
print("Publish core file: " + core.core_file) | ||
fob_core = open(core.core_file, "rb") | ||
body = {"core_file": fob_core} | ||
fob_sig = None | ||
if os.path.exists(sigfile): | ||
print("and signature file: " + sigfile) | ||
fob_sig = open(sigfile, "rb") | ||
body["signature_file"] = fob_sig | ||
else: | ||
print("(without signature file)") | ||
sf_data = None | ||
if pem: | ||
print("with certificate from: " + pem) | ||
print("to api at: " + uri) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fails if uri is not defined There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want a hardcoded default uri? If so, what should it point to? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you like to add a default, pointing to the "official" FOSSI Foundation server instance might be a good option: |
||
if args.yes: | ||
print("without confirmation") | ||
else: | ||
c = input("Confirm by typing 'yes': ") | ||
if c != "yes": | ||
print("Aborted.") | ||
return False | ||
|
||
target = uri + "/v1/publish/" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The APIs entry point is at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I choose to put the |
||
logger.debug("POST to " + target) | ||
res = requests.post(target, files=body, allow_redirects=True, verify=pem) | ||
if not res.ok: | ||
print("Request returned http result", res.status_code, res.reason) | ||
err = json.loads(res.content) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to catch more errors here. If the server responds 404 it looks like there isn't a valid json reply at all
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is a good server to test this against today without causing havoc? I have not been keeping up with recent deployments and deprecations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our internal test server is still up an running. |
||
print(json.dumps(err, indent=4)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's try to handle known errors, e.g. validation errors, in a more user-friendly way. Instead of
we could look for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be just the forwarded error messages from the FuseSoC-PD Server. So I guess it is more an server side issue. |
||
res.close() | ||
fob_core.close() | ||
if fob_sig: | ||
fob_sig.close() | ||
|
||
|
||
def gen_clean(fs, args): | ||
cachedir = os.path.join(fs.config.cache_root, "generator_cache") | ||
shutil.rmtree(cachedir, ignore_errors=True) | ||
|
@@ -538,6 +662,22 @@ def get_parser(): | |
parser_core_sign.add_argument("keyfile", help="File containing ssh private key") | ||
parser_core_sign.set_defaults(func=core_sign) | ||
|
||
parser_core_publish = core_subparsers.add_parser( | ||
"publish", help="Publish core to package db" | ||
) | ||
parser_core_publish.add_argument( | ||
"core", help="Name of the core to publish" | ||
).completer = CoreCompleter() | ||
parser_core_publish.add_argument( | ||
"--yes", help="Skip confirmation", action="store_true" | ||
) | ||
parser_core_publish.add_argument( | ||
"--autoprovider", | ||
help="Automatically add provider section if missing and possible to guess", | ||
action="store_true", | ||
) | ||
parser_core_publish.set_defaults(func=core_publish) | ||
|
||
# tool subparser | ||
parser_tool = subparsers.add_parser( | ||
"tool", help="Subcommands for dealing with tools" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there is quite a lot of new code, I would prefer to have this in a separate
publish.py
.main.py
is already way too large for its own good.