File: gh_deploy.py

package info (click to toggle)
python-mkdocs 1.6.1%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,812 kB
  • sloc: python: 14,346; javascript: 10,535; perl: 143; sh: 57; makefile: 30; xml: 11
file content (169 lines) | stat: -rw-r--r-- 5,231 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from __future__ import annotations

import logging
import os
import re
import subprocess
from typing import TYPE_CHECKING

import ghp_import  # type: ignore
from packaging import version

import mkdocs
from mkdocs.exceptions import Abort

if TYPE_CHECKING:
    from mkdocs.config.defaults import MkDocsConfig

log = logging.getLogger(__name__)

default_message = """Deployed {sha} with MkDocs version: {version}"""


def _is_cwd_git_repo() -> bool:
    try:
        proc = subprocess.Popen(
            ['git', 'rev-parse', '--is-inside-work-tree'],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
    except FileNotFoundError:
        log.error("Could not find git - is it installed and on your path?")
        raise Abort('Deployment Aborted!')
    proc.communicate()
    return proc.wait() == 0


def _get_current_sha(repo_path) -> str:
    proc = subprocess.Popen(
        ['git', 'rev-parse', '--short', 'HEAD'],
        cwd=repo_path or None,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    stdout, _ = proc.communicate()
    sha = stdout.decode('utf-8').strip()
    return sha


def _get_remote_url(remote_name: str) -> tuple[str, str] | tuple[None, None]:
    # No CNAME found.  We will use the origin URL to determine the GitHub
    # Pages location.
    remote = f"remote.{remote_name}.url"
    proc = subprocess.Popen(
        ["git", "config", "--get", remote],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    stdout, _ = proc.communicate()
    url = stdout.decode('utf-8').strip()

    if 'github.com/' in url:
        host, path = url.split('github.com/', 1)
    elif 'github.com:' in url:
        host, path = url.split('github.com:', 1)
    else:
        return None, None
    return host, path


def _check_version(branch: str) -> None:
    proc = subprocess.Popen(
        ['git', 'show', '-s', '--format=%s', f'refs/heads/{branch}'],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )

    stdout, _ = proc.communicate()
    msg = stdout.decode('utf-8').strip()
    m = re.search(r'\d+(\.\d+)+((a|b|rc)\d+)?(\.post\d+)?(\.dev\d+)?', msg, re.X | re.I)
    previousv = version.parse(m.group()) if m else None
    currentv = version.parse(mkdocs.__version__)
    if not previousv:
        log.warning('Version check skipped: No version specified in previous deployment.')
    elif currentv > previousv:
        log.info(
            f'Previous deployment was done with MkDocs version {previousv}; '
            f'you are deploying with a newer version ({currentv})'
        )
    elif currentv < previousv:
        log.error(
            f'Deployment terminated: Previous deployment was made with MkDocs version {previousv}; '
            f'you are attempting to deploy with an older version ({currentv}). Use --ignore-version '
            'to deploy anyway.'
        )
        raise Abort('Deployment Aborted!')


def gh_deploy(
    config: MkDocsConfig,
    message: str | None = None,
    force=False,
    no_history=False,
    ignore_version=False,
    shell=False,
) -> None:
    if not _is_cwd_git_repo():
        log.error('Cannot deploy - this directory does not appear to be a git repository')

    remote_branch = config.remote_branch
    remote_name = config.remote_name

    if not ignore_version:
        _check_version(remote_branch)

    if message is None:
        message = default_message
    sha = _get_current_sha(os.path.dirname(config.config_file_path))
    message = message.format(version=mkdocs.__version__, sha=sha)

    log.info(
        "Copying '%s' to '%s' branch and pushing to GitHub.",
        config.site_dir,
        config.remote_branch,
    )

    try:
        ghp_import.ghp_import(
            config.site_dir,
            mesg=message,
            remote=remote_name,
            branch=remote_branch,
            push=True,
            force=force,
            use_shell=shell,
            no_history=no_history,
            nojekyll=True,
        )
    except ghp_import.GhpError as e:
        log.error(f"Failed to deploy to GitHub with error: \n{e.message}")
        raise Abort('Deployment Aborted!')

    cname_file = os.path.join(config.site_dir, 'CNAME')
    # Does this repository have a CNAME set for GitHub Pages?
    if os.path.isfile(cname_file):
        # This GitHub Pages repository has a CNAME configured.
        with open(cname_file) as f:
            cname_host = f.read().strip()
        log.info(
            f'Based on your CNAME file, your documentation should be '
            f'available shortly at: http://{cname_host}'
        )
        log.info(
            'NOTE: Your DNS records must be configured appropriately for your CNAME URL to work.'
        )
        return

    host, path = _get_remote_url(remote_name)

    if host is None or path is None:
        # This could be a GitHub Enterprise deployment.
        log.info('Your documentation should be available shortly.')
    else:
        username, repo = path.split('/', 1)
        if repo.endswith('.git'):
            repo = repo[: -len('.git')]
        url = f'https://{username}.github.io/{repo}/'
        log.info(f"Your documentation should shortly be available at: {url}")