Skip to content
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

setup GitHub repo automatically #955

Merged
merged 1 commit into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nbdev/_modidx.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
'nbdev.cli.FilterDefaults.procs': ('09_API/cli.html#procs', 'nbdev/cli.py'),
'nbdev.cli.FilterDefaults.xtra_procs': ('09_API/cli.html#xtra_procs', 'nbdev/cli.py'),
'nbdev.cli._render_nb': ('09_API/cli.html#_render_nb', 'nbdev/cli.py'),
'nbdev.cli._update_repo_meta': ('09_API/cli.html#_update_repo_meta', 'nbdev/cli.py'),
'nbdev.cli.chelp': ('09_API/cli.html#chelp', 'nbdev/cli.py'),
'nbdev.cli.extract_tgz': ('09_API/cli.html#extract_tgz', 'nbdev/cli.py'),
'nbdev.cli.nbdev_filter': ('09_API/cli.html#nbdev_filter', 'nbdev/cli.py'),
Expand Down
19 changes: 18 additions & 1 deletion nbdev/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,30 @@ def _render_nb(fn, cfg):
fn.write_text(txt)

# %% ../nbs/09_API/12_cli.ipynb 11
def _update_repo_meta(cfg):
"Enable gh pages and update the homepage and description in your GitHub repo."
token=os.getenv('GITHUB_TOKEN')
if token:
from ghapi.core import GhApi
api = GhApi(owner=cfg.user, repo=cfg.repo, token=token)
try: # repo needs something in it before you can enable pages
cmds = L(['git add settings.ini', "git commit -m'add settings'", 'git config push.default current', 'git push'])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you are first initializing a github repo, it cannot be empty before you enable pages. It has to contain at least one file. I don't love executing git commands on behalf of the user. Another alternative would be to commit an empty file, but that clutters the repo IMO.

Curious on what your opinions are here. I put this in its own try block because I suspect something could go wrong here and I don't want to disrupt the onboarding process.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine - whether we exec git for the user vs use ghapi for the user seems much the same afaict.

FYI I don't think map here is useful -- seems a plain for loop would be simpler and just as concise. Generally map is most useful for the situation where you want to return a list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least until we release it, perhaps best not to have the try, so we can find out if there are errors, and if so, what errors come up?

cmds.map(partial(run, ignore_ex=True))
api.enable_pages(branch='gh-pages')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the repo is empty, we get a 403 error: conflict if trying to enable pages. Depending on how you create your repo before initialiing nbdev this is problematic. This is why the git commit step exists above.

except HTTPError: print("Could not enable GitHub Pages automatically.")
try: api.repos.update(homepage=f'{cfg.doc_host}/{cfg.doc_baseurl}', description=cfg.description)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are able to update the homepage and description with ghapi!

except HTTPError:print(f"Could not update the description & URL on the repo: {cfg.user}/{cfg.repo} using $GITHUB_TOKEN.\n"
"Use a token with the correction permissions or perform these steps manually.")

# %% ../nbs/09_API/12_cli.ipynb 12
@call_parse
@delegates(nbdev_create_config)
def nbdev_new(**kwargs):
"Create an nbdev project."
from ghapi.core import GhApi
nbdev_create_config.__wrapped__(**kwargs)
cfg = get_config()
_update_repo_meta(cfg)

path = Path()
tag = GhApi().repos.get_latest_release('fastai', 'nbdev-template').tag_name
Expand All @@ -108,7 +125,7 @@ def nbdev_new(**kwargs):
nbdev_export.__wrapped__()
nbdev_readme.__wrapped__()

# %% ../nbs/09_API/12_cli.ipynb 14
# %% ../nbs/09_API/12_cli.ipynb 15
@call_parse
def chelp():
"Show help for all console scripts"
Expand Down
43 changes: 42 additions & 1 deletion nbs/09_API/12_cli.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,30 @@
" fn.write_text(txt)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dd385911-aa8f-44e7-8d46-7b8a20f3b010",
"metadata": {},
"outputs": [],
"source": [
"#|export\n",
"def _update_repo_meta(cfg):\n",
" \"Enable gh pages and update the homepage and description in your GitHub repo.\"\n",
" token=os.getenv('GITHUB_TOKEN')\n",
" if token: \n",
" from ghapi.core import GhApi\n",
" api = GhApi(owner=cfg.user, repo=cfg.repo, token=token)\n",
" try: # repo needs something in it before you can enable pages\n",
" cmds = L(['git add settings.ini', \"git commit -m'add settings'\", 'git config push.default current', 'git push']) \n",
" cmds.map(partial(run, ignore_ex=True))\n",
" api.enable_pages(branch='gh-pages')\n",
" except HTTPError: print(\"Could not enable GitHub Pages automatically.\")\n",
" try: api.repos.update(homepage=f'{cfg.doc_host}/{cfg.doc_baseurl}', description=cfg.description)\n",
" except HTTPError:print(f\"Could not update the description & URL on the repo: {cfg.user}/{cfg.repo} using $GITHUB_TOKEN.\\n\"\n",
" \"Use a token with the correction permissions or perform these steps manually.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -192,6 +216,7 @@
" from ghapi.core import GhApi\n",
" nbdev_create_config.__wrapped__(**kwargs)\n",
" cfg = get_config()\n",
" _update_repo_meta(cfg)\n",
"\n",
" path = Path()\n",
" tag = GhApi().repos.get_latest_release('fastai', 'nbdev-template').tag_name\n",
Expand Down Expand Up @@ -302,7 +327,23 @@
"execution_count": null,
"id": "3d8031ce",
"metadata": {},
"outputs": [],
"outputs": [
{
"ename": "TypeError",
"evalue": "__init__() got an unexpected keyword argument 'types'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [13]\u001b[0m, in \u001b[0;36m<cell line: 2>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#|hide\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnbdev\u001b[39;00m; \u001b[43mnbdev\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mnbdev_export\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/fastcore/script.py:108\u001b[0m, in \u001b[0;36mcall_parse.<locals>._f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[38;5;129m@wraps\u001b[39m(func)\n\u001b[1;32m 106\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_f\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 107\u001b[0m mod \u001b[38;5;241m=\u001b[39m inspect\u001b[38;5;241m.\u001b[39mgetmodule(inspect\u001b[38;5;241m.\u001b[39mcurrentframe()\u001b[38;5;241m.\u001b[39mf_back)\n\u001b[0;32m--> 108\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m mod: \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 109\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m SCRIPT_INFO\u001b[38;5;241m.\u001b[39mfunc \u001b[38;5;129;01mand\u001b[39;00m mod\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;241m==\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m\"\u001b[39m: SCRIPT_INFO\u001b[38;5;241m.\u001b[39mfunc \u001b[38;5;241m=\u001b[39m func\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[1;32m 110\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(sys\u001b[38;5;241m.\u001b[39margv)\u001b[38;5;241m>\u001b[39m\u001b[38;5;241m1\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m sys\u001b[38;5;241m.\u001b[39margv[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;241m==\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m'\u001b[39m: sys\u001b[38;5;241m.\u001b[39margv\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;241m1\u001b[39m)\n",
"File \u001b[0;32m~/github/nbdev/nbdev/doclinks.py:121\u001b[0m, in \u001b[0;36mnbdev_export\u001b[0;34m(path, **kwargs)\u001b[0m\n\u001b[1;32m 119\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExport notebooks in `path` to Python modules\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 120\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m os\u001b[38;5;241m.\u001b[39menviron\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mIN_TEST\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;241m0\u001b[39m): \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[0;32m--> 121\u001b[0m files \u001b[38;5;241m=\u001b[39m \u001b[43mnbglob\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 122\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m f \u001b[38;5;129;01min\u001b[39;00m files: nb_export(f)\n\u001b[1;32m 123\u001b[0m add_init(get_config()\u001b[38;5;241m.\u001b[39mlib_path)\n",
"File \u001b[0;32m~/github/nbdev/nbdev/doclinks.py:93\u001b[0m, in \u001b[0;36mnbglob\u001b[0;34m(path, skip_folder_re, file_glob, skip_file_re, key, as_path, **kwargs)\u001b[0m\n\u001b[1;32m 90\u001b[0m \u001b[38;5;129m@delegates\u001b[39m(globtastic, but\u001b[38;5;241m=\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfile_glob\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mskip_folder_re\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mskip_file_re\u001b[39m\u001b[38;5;124m'\u001b[39m))\n\u001b[1;32m 91\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mnbglob\u001b[39m(path\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, skip_folder_re \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m^[_.]\u001b[39m\u001b[38;5;124m'\u001b[39m, file_glob\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m*.ipynb\u001b[39m\u001b[38;5;124m'\u001b[39m, skip_file_re\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m^[_.]\u001b[39m\u001b[38;5;124m'\u001b[39m, key\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnbs_path\u001b[39m\u001b[38;5;124m'\u001b[39m, as_path\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 92\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFind all files in a directory matching an extension given a config key.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 93\u001b[0m path \u001b[38;5;241m=\u001b[39m Path(path \u001b[38;5;129;01mor\u001b[39;00m \u001b[43mget_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m[key])\n\u001b[1;32m 94\u001b[0m recursive\u001b[38;5;241m=\u001b[39mget_config()\u001b[38;5;241m.\u001b[39mrecursive\n\u001b[1;32m 95\u001b[0m res \u001b[38;5;241m=\u001b[39m globtastic(path, file_glob\u001b[38;5;241m=\u001b[39mfile_glob, skip_folder_re\u001b[38;5;241m=\u001b[39mskip_folder_re,\n\u001b[1;32m 96\u001b[0m skip_file_re\u001b[38;5;241m=\u001b[39mskip_file_re, recursive\u001b[38;5;241m=\u001b[39mrecursive, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
"File \u001b[0;32m~/github/nbdev/nbdev/config.py:193\u001b[0m, in \u001b[0;36mget_config\u001b[0;34m(cfg_name, path)\u001b[0m\n\u001b[1;32m 191\u001b[0m cfg_file \u001b[38;5;241m=\u001b[39m _nbdev_config_file(cfg_name, path)\n\u001b[1;32m 192\u001b[0m extra_files \u001b[38;5;241m=\u001b[39m _xdg_config_paths(cfg_name)\n\u001b[0;32m--> 193\u001b[0m cfg \u001b[38;5;241m=\u001b[39m \u001b[43mConfig\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcfg_file\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparent\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcfg_file\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mextra_files\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextra_files\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtypes\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_types\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 194\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _apply_defaults(cfg)\n",
"\u001b[0;31mTypeError\u001b[0m: __init__() got an unexpected keyword argument 'types'"
]
}
],
"source": [
"#|hide\n",
"import nbdev; nbdev.nbdev_export()"
Expand Down