chore: fix to vsix

This commit is contained in:
yazart
2026-06-10 17:23:29 +03:00
parent 3e177b3adf
commit de65873e45
15 changed files with 762 additions and 26 deletions
+28 -26
View File
@@ -1,40 +1,42 @@
#!/bin/bash
mkdir input report output
export NPM_RUNTIME_CHECK_VER=latest
PACKAGE_NAME=${1}
PACKAGE_VERSION=${2}
set -e
RESULT_NAME=$PACKAGE_NAME
if [ ${PACKAGE_NAME:0:1} == '@' ]
then
POS=$(echo $PACKAGE_NAME | grep -ob "/" | grep -oE "[0-9]+" | head -n 1)
RESULT_NAME=${PACKAGE_NAME:$POS+1}
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <publisher.extension> <version>"
exit 1
fi
URL=$(npm view ${PACKAGE_NAME}@${PACKAGE_VERSION} dist.tarball)
PACKAGE_NAME=$1
PACKAGE_VERSION=$2
REPORT=$(ls ./report/git_package)
REPORT_LEN=${#REPORT}
if [ ${REPORT_LEN} != 0 ]
then
if [[ "$PACKAGE_NAME" != *.* ]]; then
echo "Package name must use publisher.extension format"
exit 1
fi
PUBLISHER=${PACKAGE_NAME%%.*}
EXTENSION=${PACKAGE_NAME#*.}
URL="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${PUBLISHER}/vsextensions/${EXTENSION}/${PACKAGE_VERSION}/vspackage"
RESULT_INPUT="${PACKAGE_NAME}-${PACKAGE_VERSION}.vsix"
mkdir -p input report output
export VSIX_RUNTIME_CHECK_VER=${VSIX_RUNTIME_CHECK_VER:-latest}
if [ -d ./report/git_package ]; then
sync
rm -rf ./report/git_package
echo "Clean git_package"
fi
RESULT_INPUT=${RESULT_NAME}-${PACKAGE_VERSION}.tgz
cd input
if [ $(ls $RESULT_INPUT) ]
then
rm $RESULT_INPUT
fi
set -x
echo $URL
wget -O "${RESULT_INPUT}" "${URL}"
cd ..
echo "Download ${PACKAGE_NAME}@${PACKAGE_VERSION} from ${URL}"
curl \
--fail \
--location \
--header "Accept: application/octet-stream" \
--header "Accept-Encoding: identity" \
--output "input/${RESULT_INPUT}" \
"${URL}"
export RELOAD_CONFIG=1
export ADD_METADATA_VOLUME='true'
+11
View File
@@ -0,0 +1,11 @@
# The VSIX manifest points at angular/angular, but the VS Code extension source
# lives in angular/vscode-ng-language-service. There is no v20.3.3 tag there;
# v20.3.0 is the nearest public tag for the 20.3 line.
install_dependencies: "corepack enable && corepack prepare yarn@1.22.22 --activate && yarn install --frozen-lockfile"
source_repository: "https://github.com/angular/vscode-ng-language-service.git"
source_ref: "v20.3.0"
build_vsix: "yarn package"
run_tests: "yarn test"
coverage:
enabled: false
threshold: 80
View File
+9
View File
@@ -0,0 +1,9 @@
# Marketplace version 3.0.19 is tagged as pre-release/3.0.19 upstream.
install_dependencies: "npm ci"
source_ref: "pre-release/3.0.19"
build_vsix: "npx @vscode/vsce package --out source.vsix"
run_tests: "npx c8 --clean --temp-directory coverage/tmp npm test"
coverage:
enabled: true
tool: "c8"
threshold: 80
+8
View File
@@ -0,0 +1,8 @@
# Commands are executed from the cloned repository root.
install_dependencies: "node -e 'const [major, minor] = process.versions.node.split(`.`).map(Number); if (major < 22 || (major === 22 && minor < 18)) { console.error(`GitLens 17.12.1 requires Node >=22.18.0; current=${process.versions.node}`); process.exit(1); }' && corepack enable && corepack prepare pnpm@10.33.0 --activate && pnpm install --frozen-lockfile"
build_vsix: "pnpm exec vsce package --no-dependencies --out source.vsix"
run_tests: "npx c8 --clean --temp-directory coverage/tmp node_modules/.bin/vscode-test"
coverage:
enabled: true
tool: "c8"
threshold: 80
+6
View File
@@ -0,0 +1,6 @@
install_dependencies: "npm ci"
build_vsix: "npx vsce package --out source.vsix"
run_tests: "npm test"
coverage:
enabled: false
threshold: 80
+6
View File
@@ -0,0 +1,6 @@
install_dependencies: "corepack enable && corepack prepare yarn@1.22.22 --activate && yarn install --frozen-lockfile"
build_vsix: "npx vsce package --out source.vsix"
run_tests: "yarn test"
coverage:
enabled: false
threshold: 80
+7
View File
@@ -0,0 +1,7 @@
install_dependencies: "npm ci"
build_vsix: "npx vsce package --out source.vsix"
run_tests: "npm run build-bundle && npm run jest -- --coverage"
coverage:
enabled: true
tool: "jest"
threshold: 80
Executable
+1
View File
@@ -0,0 +1 @@
#!/bin/bash
+4
View File
@@ -0,0 +1,4 @@
GitPython
PyYAML
wget
scapy
+637
View File
@@ -0,0 +1,637 @@
#!/usr/bin/python3
import os
import json
import logging
import os.path
import pathlib
import argparse
import tempfile
import subprocess
import zipfile
from urllib.parse import urlparse
import yaml
from runtime_check.checker import T5Checker, Scanfeeder
from runtime_check.logger import get_logger
from runtime_check.monitor import Monitor
from runtime_check.config import settings
MANUAL_PROCESSING_KEY = 'MANUAL_CHECK'
MANUAL_CHECK_DETECTION_MESSAGE = 'MANUAL_CHECK_DETECTION'
class VSIX_T5Checker(T5Checker):
"""Base class to perform the whole check. We may inherit it and overwrite any part in some specific case, so don't hesitate"""
def __init__(
self,
scanfeeder: Scanfeeder,
monitor: Monitor,
logger: logging.Logger,
report_dir: pathlib.Path,
package_path: pathlib.Path,
):
self.package_path = pathlib.Path(package_path)
super().__init__(scanfeeder, monitor, logger, report_dir)
def _load_yaml_config(self) -> None:
self.packages_info = dict()
yaml_base_info = dict()
yaml_specific_version = dict()
stage_name='load_yaml_config'
metadata_root = pathlib.Path(settings.get("metadata_path", "../metadata"))
coverage_tool_paths = (
metadata_root / "coverage_tools.yaml",
pathlib.Path("../meta/coverage_tools.yaml"),
)
coverage_tool_path = next(
(path for path in coverage_tool_paths if path.exists()),
None,
)
if coverage_tool_path:
with coverage_tool_path.open(encoding="utf-8") as coverage_file:
self.supported_coverage_tools = yaml.load(
coverage_file,
Loader=yaml.SafeLoader,
) or {}
else:
self.stage_error(
stage_name=stage_name,
details=(
"Failed to load supported coverage tools yaml file from "
+ ", ".join(str(path) for path in coverage_tool_paths)
),
)
package_metadata_paths = (
metadata_root / settings.package_name / "metadata.yaml",
metadata_root / f"{settings.package_name}.yml",
metadata_root / f"{settings.package_name}.yaml",
)
package_metadata_path = next(
(path for path in package_metadata_paths if path.exists()),
None,
)
package_specific_version = (
metadata_root
/ settings.package_name
/ settings.package_version
/ "metadata.yaml"
)
if package_metadata_path:
with package_metadata_path.open(encoding="utf-8") as metadata_file:
yaml_base_info = yaml.load(
metadata_file,
Loader=yaml.SafeLoader,
) or {}
if package_specific_version.exists():
with package_specific_version.open(encoding="utf-8") as version_file:
yaml_specific_version = yaml.load(
version_file,
Loader=yaml.SafeLoader,
) or {}
yaml_base_info.update(yaml_specific_version)
self._normalize_vsix_metadata(yaml_base_info)
self.packages_info[settings.package_name] = yaml_base_info
else:
self.packages_info[settings.package_name] = dict()
self.logger.info("[LOAD METADATA]: not found description for package use default")
self.diff_exclude_files = []
self.diff_exclude_extensions = []
self.check_manual_processing()
@staticmethod
def _normalize_vsix_metadata(package_info: dict) -> None:
aliases = {
"install_dependencies": "install_actions",
"build_vsix": "build_actions",
"run_tests": "coverage_command",
"source_repository": "repository",
}
for source_key, target_key in aliases.items():
if source_key in package_info and target_key not in package_info:
package_info[target_key] = package_info[source_key]
coverage = package_info.get("coverage")
if isinstance(coverage, dict):
if "tool" in coverage and "coverage_tool" not in package_info:
package_info["coverage_tool"] = coverage["tool"]
if "enabled" in coverage and "coverage_enabled" not in package_info:
package_info["coverage_enabled"] = coverage["enabled"]
for value in package_info.values():
if isinstance(value, dict) and value is not coverage:
VSIX_T5Checker._normalize_vsix_metadata(value)
def check_manual_processing(self) -> None:
if self.get_version_specific_package_info(MANUAL_PROCESSING_KEY):
self.status.append_status_file(self.status.MANUAL_CHECK, '"Based on metadata info, manual check (T06) required"')
self.logger.info(MANUAL_CHECK_DETECTION_MESSAGE)
self.stage_warn_without_exit(
stage_name="manual_check_required",
details=f"Manual check is required to proceed with this package. \n{MANUAL_CHECK_DETECTION_MESSAGE}\n"
)
self.check_is_done()
def extract_package(self, archive_path: pathlib.Path, result_folder: pathlib.Path, substep_name: str) -> pathlib.Path:
try:
result_folder.mkdir(parents=True, exist_ok=False)
result_root = result_folder.resolve()
with zipfile.ZipFile(archive_path) as archive:
for member in archive.infolist():
destination = (result_folder / member.filename).resolve()
if destination != result_root and result_root not in destination.parents:
raise ValueError(f"Unsafe path in VSIX archive: {member.filename}")
archive.extractall(result_folder)
except (OSError, ValueError, zipfile.BadZipFile) as e:
self.stage_error(
stage_name=substep_name,
details=f"Failed to extract VSIX archive {archive_path}: {e}.",
)
package_json = result_folder / "extension" / "package.json"
if not package_json.is_file():
self.stage_error(
stage_name=substep_name,
details=f"VSIX archive {archive_path} does not contain extension/package.json.",
)
self.stage_passed(stage_name=substep_name)
return result_folder
def load_extracted_package_json(self, package_extracted_path: pathlib.Path) -> None:
stage_name='load_extracted_package_json'
try:
with (package_extracted_path / "extension" / "package.json").open(
encoding="utf-8"
) as package_json:
self.extracted_package_info = json.load(package_json)
except (OSError, json.JSONDecodeError) as e:
self.stage_error(
stage_name=stage_name,
details=f"Failed to load extension/package.json from VSIX: {e}",
)
self.stage_passed(stage_name=stage_name)
def get_git_url(self):
try:
repo_url = self.get_version_specific_package_info("repository")
if isinstance(repo_url, dict):
repo_url = repo_url.get("url")
if not repo_url:
repository = self.extracted_package_info.get("repository")
if isinstance(repository, str):
repo_url = repository
elif isinstance(repository, dict):
repo_url = repository.get("url")
if not repo_url:
self.status.append_status_file(self.status.GIT_URL_ABSENT, '"Git url is absent in package info and metadata"')
self.stage_error(
stage_name="get_git_url",
details="Failed to fetch git url.",
)
repo_url = repo_url.removeprefix("git+")
if repo_url.startswith("git@github.com:"):
repo_url = "https://github.com/" + repo_url.removeprefix("git@github.com:")
parsed = urlparse(repo_url)
if parsed.hostname != "github.com":
self.status.append_status_file(self.status.GIT_URL_PARSE_FAILED, '"Failed to parse git url - not a github url"')
self.stage_error(
stage_name="get_git_url",
details=f"Failed to extract package repository - {repo_url}",
)
parts = [part for part in parsed.path.split("/") if part]
if len(parts) < 2:
raise ValueError(f"GitHub repository path is incomplete: {parsed.path}")
repo_url = "https://github.com/" + "/".join(parts[:2])
except Exception as e:
self.status.append_status_file(self.status.GIT_URL_EXTRACT_FAILED, '"Failed to extract git url - not a github url"')
self.stage_error(
stage_name="get_git_url",
details=f"Failed to extract package repository: {e}",
)
self.stage_passed(
stage_name="get_git_url",
details="git url successfully extracted"
)
self.logger.info("Git url for the project is: %s", repo_url)
return repo_url
def clone_package_and_checkout(self, working_dir: pathlib.Path) -> pathlib.Path:
stage_name = "clone_package_and_checkout"
repo_url = self.get_git_url()
project_dir = working_dir / "git_package" / self.package_name
project_dir.parent.mkdir(parents=True, exist_ok=True)
try:
subprocess.run(
["git", "clone", repo_url, str(project_dir)],
check=True,
text=True,
capture_output=True,
)
source_ref = self.get_version_specific_package_info("source_ref")
if source_ref:
subprocess.run(
["git", "fetch", "origin", str(source_ref)],
cwd=project_dir,
check=True,
text=True,
capture_output=True,
)
subprocess.run(
["git", "checkout", "--detach", "FETCH_HEAD"],
cwd=project_dir,
check=True,
text=True,
capture_output=True,
)
else:
commit_id = self.get_version_specific_package_info("commit_id")
if commit_id:
subprocess.run(
["git", "checkout", "--detach", str(commit_id)],
cwd=project_dir,
check=True,
text=True,
capture_output=True,
)
else:
tags = subprocess.run(
["git", "tag", "--list", self.version, f"v{self.version}"],
cwd=project_dir,
check=True,
text=True,
capture_output=True,
).stdout.splitlines()
if tags:
preferred_tag = self.version if self.version in tags else tags[0]
subprocess.run(
["git", "checkout", "--detach", preferred_tag],
cwd=project_dir,
check=True,
text=True,
capture_output=True,
)
else:
self.logger.warning(
"No tag matching %s or v%s; checking current repository HEAD",
self.version,
self.version,
)
subprocess.run(
["git", "submodule", "update", "--init", "--recursive"],
cwd=project_dir,
check=True,
text=True,
capture_output=True,
)
except (OSError, subprocess.CalledProcessError) as e:
stderr = getattr(e, "stderr", None)
self.stage_error(
stage_name=stage_name,
details=f"Failed to clone or checkout {repo_url}: {stderr or e}",
)
self.stage_passed(stage_name=stage_name, details="Finished downloading package sources")
return project_dir
def load_repo_package_info(self, package_dir):
package_file_path = self.get_version_specific_package_info('repo_package_json_path')
if not package_file_path:
package_file_path = self.get_package_info('repo_package_json_path')
if not package_file_path:
package_file_path = "package.json"
try:
with (package_dir / package_file_path).open(encoding="utf-8") as package_json:
res = json.load(package_json)
if 'scripts' in res:
from pprint import pformat
self.logger.debug("Package Scripts: %s", pformat(res['scripts']))
except json.JSONDecodeError as e:
self.stage_error(
stage_name="load_repo_package_info",
details=f"Failed to load repo package info - failed to decode {package_file_path} json {e.msg}",
)
except OSError as e:
self.stage_error(
stage_name="load_repo_package_info",
details=f"Failed to load repo package info - failed to open {package_file_path}: {e}",
)
self.stage_passed(stage_name="load_repo_package_info")
return res
def install_package(
self,
*,
package_dir: pathlib.Path,
env: dict,
**kwargs,
) -> None:
actions = self.get_actions_from_config("install_actions")
if actions is None:
self.install_package_general(package_dir=package_dir, env=env)
else:
self.run_actions(
"install_package",
actions,
env=env,
package_dir=package_dir,
check=True,
timeout=self.install_timeout,
)
self.stage_passed(stage_name="install_package", details="Dependencies were installed.")
def install_package_general(self, package_dir: pathlib.Path, env: dict) -> bool:
try:
if (package_dir / "pnpm-lock.yaml").is_file():
actions = [
"corepack enable",
"pnpm install --frozen-lockfile",
]
elif (package_dir / "yarn.lock").is_file():
actions = [
"corepack enable",
"yarn install --frozen-lockfile --non-interactive",
]
elif (package_dir / "package-lock.json").is_file():
actions = ["npm ci"]
else:
actions = ["npm install --no-audit"]
return self.run_actions(
"install_package_general",
actions,
env=env,
package_dir=package_dir,
check=True,
timeout=self.install_timeout,
)
except Exception as e:
self.stage_error(
stage_name="install_package_general",
details=f"Failed to install source dependencies: {e}",
)
def custom_prepare(self, package_dir: str | pathlib.Path, env: dict) -> bool:
"""Run prepare actions from yaml file"""
self.logger.info("Run custom package preparation")
prepare = self.get_actions_from_config('prepare')
result = self.run_actions(
'prepare',
prepare,
env=env,
package_dir=package_dir,
check=True,
timeout=self.install_timeout
)
return result
def build_package(
self,
*,
package_dir: pathlib.Path,
env: dict,
**kwargs,
) -> bool:
actions = self.get_actions_from_config("build_actions")
if actions is None:
result = self.build_package_general(package_dir=package_dir, env=env)
else:
result = self.run_actions(
"build_package",
actions,
env=env,
package_dir=package_dir,
check=True,
timeout=self.build_timeout,
)
self.stage_passed(stage_name="build_package", details="VSIX was built successfully.")
return result
def build_package_general(self, env: dict, package_dir: str | pathlib.Path) -> bool:
return self.run_actions(
'build_package_general',
["npx @vscode/vsce package --out source.vsix"],
env=env,
package_dir=package_dir,
check=True,
timeout=self.build_timeout
)
def find_built_vsix(
self,
package_dir: pathlib.Path,
existing_archives: dict[pathlib.Path, int],
) -> pathlib.Path:
configured_path = self.get_version_specific_package_info("built_vsix_path")
if configured_path:
built_vsix = package_dir / configured_path
if built_vsix.is_file():
return built_vsix
self.stage_error(
stage_name="find_built_vsix",
details=f"Configured built VSIX was not found: {built_vsix}",
)
candidates = []
for archive in package_dir.rglob("*.vsix"):
mtime = archive.stat().st_mtime_ns
if archive not in existing_archives or existing_archives[archive] != mtime:
candidates.append(archive)
if not candidates:
self.stage_error(
stage_name="find_built_vsix",
details="Build command did not create or update a VSIX archive.",
)
built_vsix = max(candidates, key=lambda path: path.stat().st_mtime_ns)
self.stage_passed(
stage_name="find_built_vsix",
details=f"Built VSIX found at {built_vsix}",
)
return built_vsix
def count_coverage_custom(self, env: dict, package_dir: str | pathlib.Path) -> None:
coverage_actions = self.get_actions_from_config("coverage_command")
if not coverage_actions:
# No actions provided. This is weird but who to judge?
return
self.logger.info("Run custom package coverage")
self.run_actions_with_monitor(
'count_coverage_custom',
coverage_actions,
env=env,
check=False,
package_dir=package_dir,
timeout=self.test_timeout
)
return
def count_coverage_general(self, env: dict, package_dir: str | pathlib.Path, **kwargs) -> None:
self.status.append_status_file(self.status.COVERAGE_COMMAND_ABSENT, '"TEST_COMMAND section in metadate must be filled"')
self.stage_error(
stage_name='count_coverage_general',
details="Coverage command for the VSIX source repository is not configured."
)
def run_coverage_report(self, package_dir: pathlib.Path, env: dict) -> str:
coverage_tool_name = self.get_version_specific_package_info('coverage_tool')
if coverage_tool_name not in self.supported_coverage_tools:
self.stage_error(
stage_name="run_coverage_report",
details=f"Unsupported coverage tool: `{coverage_tool_name}`"
)
coverage_tool = self.supported_coverage_tools[coverage_tool_name]
coverage_report_folder = coverage_tool['coverage_report_folder']
# Will travers from 'build_path' up to 'package_path' in hope to find coverage dir.
build_relative_path = self.get_version_specific_package_info('build_relative_path')
if build_relative_path:
probe_path = package_dir / build_relative_path
while probe_path != package_dir:
if (probe_path / coverage_report_folder).exists():
package_dir = probe_path
break
probe_path = probe_path.parent
if not (package_dir / coverage_report_folder).exists():
self.stage_error(
stage_name="run_coverage_report",
details=f"Failed to find coverage report dir."
)
# TODO: capture report and save in metadata
coverage_report = self.run_actions(
'run_coverage_report',
coverage_tool['report'],
env=env,
check=True,
package_dir=package_dir,
)
self.stage_passed('run_coverage_report', details=coverage_report)
coverage_report = self.run_actions(
'process_coverage_result',
coverage_tool['check'],
env=env,
check=True,
package_dir=package_dir,
)
self.stage_passed('process_coverage_result', details=coverage_report)
def run_tests_coverage(self, env: dict, package_dir: str | pathlib.Path, **kwargs) -> None:
if self.get_version_specific_package_info("coverage_enabled") is False:
self.stage_passed(
stage_name="count_coverage",
details="Coverage verification is disabled for this VSIX package.",
)
return
coverage_actions = self.get_actions_from_config("coverage_command")
if coverage_actions is None:
self.count_coverage_general(env=env, package_dir=package_dir, **kwargs)
else:
self.count_coverage_custom(env, package_dir)
self.run_coverage_report(package_dir, env)
self.stage_passed(
stage_name="count_coverage",
details=f"Package {self.package_name} {self.version} was processed."
)
@staticmethod
def get_package_env():
env = os.environ.copy()
new_env_path = []
for path in env['PATH'].split(os.pathsep):
if path.endswith('venv/bin'):
# erase current venv
continue
new_env_path.append(path)
env['PATH'] = os.pathsep.join(new_env_path)
env.pop('PYTHONHOME', None)
return env
def run_check(self):
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir_path = pathlib.Path(tmpdir)
marketplace_extracted_path = self.extract_package(
archive_path=self.package_path,
result_folder=tmpdir_path / "marketplace_vsix",
substep_name="extract_marketplace_vsix",
)
self.load_extracted_package_json(marketplace_extracted_path)
self.logger.info("Working on VSIX package %s@%s", self.package_name, self.version)
git_project_path = self.clone_package_and_checkout(
working_dir=pathlib.Path(self.report_dir)
)
self.repo_package_info = self.load_repo_package_info(git_project_path)
package_env = self.get_package_env()
self.custom_prepare(package_dir=git_project_path, env=package_env)
self.install_package(package_dir=git_project_path, env=package_env)
existing_archives = {
archive: archive.stat().st_mtime_ns
for archive in git_project_path.rglob("*.vsix")
}
self.build_package(package_dir=git_project_path, env=package_env)
built_vsix = self.find_built_vsix(git_project_path, existing_archives)
source_extracted_path = self.extract_package(
archive_path=built_vsix,
result_folder=tmpdir_path / "source_vsix",
substep_name="extract_source_vsix",
)
self.check_diff(marketplace_extracted_path, source_extracted_path)
self.run_tests_coverage(package_dir=git_project_path, env=package_env)
self.check_is_done()
def main(args):
report_folder = args.report_path
package_file_name = settings.package_file
logger = get_logger(
"vsix_package_processing",
log_file=pathlib.Path(report_folder) / f"processing_{package_file_name}.log",
log_level_name=settings.log_level.upper()
)
logger.info("Start processing %s", package_file_name)
scanfeeder = Scanfeeder(logger)
monitor = Monitor(
tcpdump_enable=settings.monitor_enable,
sysdig_enable=settings.monitor_enable,
scanfeeder=scanfeeder,
logger=logger,
pipe_path=settings.sysdig_pipe_path,
report_folder=report_folder,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
vsix_checker = VSIX_T5Checker(
scanfeeder=scanfeeder,
monitor=monitor,
logger=logger,
report_dir=pathlib.Path(args.report_path),
package_path=pathlib.Path(args.file_path),
)
vsix_checker.run_check()
if __name__ == "__main__":
projdir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
parser = argparse.ArgumentParser(prog="T005 checker", description="does t005 check")
parser.add_argument("--file_path", help="full path to the archive to be check", required=False, default=os.path.join(projdir, 'input', settings.package_file))
parser.add_argument("--report_path", help="full path to the directory where report will be generated", required=False, default=os.path.join(projdir, 'report'))
args = parser.parse_args()
main(args)
+3
View File
@@ -0,0 +1,3 @@
Host github.com
User git
IdentityFile ~/.ssh/github_rsa
+38
View File
@@ -0,0 +1,38 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
+1
View File
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgGp47LrHXo6Ghtx1ESc4AlPT/SalJL2y+le4Vf/KIUIB7PRI5bbFV1VUOM8jLPyK0WETHG0mZmaOn64hBTh9hqvOQSdAEcaa2ZAksa9ELTgK+OgovOOaTINXxib1uZjiGHx91LfAweOD4lopYA31/ffiCklponq4G8OwUYLjUZg3YRZd3VyKDcRjwhDPOpmMLSHJZztAek2PM8eMf8h09fMESMgSFI3T6z9IIpfnRwIkFwK7XujqdS5qNJARX4VsI4TFay8JWn813b3x6IexCEHvVmstS2xa7e0fgWHk+CUui9ut63fM/O/Uap8LTdAm7dnlfTXVCIYXZLofiBGML1Hmc0//8649w28mbd9cXBcBDrFnnFRObhwYK7cgJGk4lfveLLQJHeIV0IjpK+UE70LMoChF1x9eWc+8DW6w7KxjpqXsy1/s51D5lMAjZ9p6PpCZDeogVH0eI2qezbK10dBTqH9KUZvrGnDuC9QQAfHhvvTtme/YkJy8zK+jkQ/ohQ== x@x
+3
View File
@@ -0,0 +1,3 @@
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=