Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Migrate artifact hosting to cloudsmith #394

Merged
merged 24 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
10b24e4
Unset application/json as header in cargo publish
krishnangovindraj Jan 3, 2024
9b9dbad
WIP: Implementing CloudsmithDeployment. Artifact works
krishnangovindraj Jan 3, 2024
71a79e0
Add remaining important repo types
krishnangovindraj Jan 3, 2024
3732707
WIP: Plumbing around apt deploy.py for cloudsmith wrapper
krishnangovindraj Jan 4, 2024
51dd9b4
Artifact works?
krishnangovindraj Jan 4, 2024
3c1f734
Maven
krishnangovindraj Jan 4, 2024
50828d6
Apt
krishnangovindraj Jan 4, 2024
eeeb7fb
Remove all RPM related code and docs
krishnangovindraj Jan 4, 2024
347c861
Add helm deployment
krishnangovindraj Jan 4, 2024
ffd7d4d
Increase sync attempts
krishnangovindraj Jan 4, 2024
c11c66c
Update APT rules to use generated package filename instead of package…
krishnangovindraj Jan 5, 2024
13340b1
Replace repo.vaticle from npm rule docs
krishnangovindraj Jan 5, 2024
deb89ba
Remove unused lines in artifact deploy.py
krishnangovindraj Jan 5, 2024
21ec936
Update artifact_file rule; update crateDeployer for trailing /
krishnangovindraj Jan 8, 2024
699ece2
Increase sync timeout to 5 minutes
krishnangovindraj Jan 10, 2024
4226b36
Trigger CI
krishnangovindraj Jan 10, 2024
09e4085
Trigger CI
krishnangovindraj Jan 10, 2024
6280fa9
Fix workspace initialisation of cloudsmith deps
krishnangovindraj Jan 10, 2024
4744ec5
Minimize cloudsmith requirements file
krishnangovindraj Jan 10, 2024
38c6d27
1/2 before renaming
krishnangovindraj Jan 12, 2024
72ef8d6
2/2 refactor, but now it needs propagation
krishnangovindraj Jan 12, 2024
4c63d32
Fixes
krishnangovindraj Jan 12, 2024
b622817
Fix and test one of each
krishnangovindraj Jan 13, 2024
f3688df
Remove stray print
krishnangovindraj Jan 13, 2024
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
5 changes: 0 additions & 5 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ stardoc(
"//npm/deploy:lib",
"//packer:lib",
"//pip:lib",
"//rpm:lib",
],
symbol_names = [
# From: //apt:rules.bzl
Expand Down Expand Up @@ -106,9 +105,5 @@ stardoc(
# From: //pip:rules.bzl
"assemble_pip",
"deploy_pip",

# From: //rpm:rules.bzl
"assemble_rpm",
"deploy_rpm",
],
)
58 changes: 2 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ deploy_npm(<a href="#deploy_npm-name">name</a>, <a href="#deploy_npm-release">re
## How to generate an auth token

### Using the command line (`npm adduser`)
1. Run `npm adduser &lt;repo_url&gt;` (example: `npm adduser --registry=https://repo.vaticle.com/repository/npm-private`)
1. Run `npm adduser &lt;repo_url&gt;` (example: `npm adduser --registry=https://npm.cloudsmith.io/typedb/private/`)
2. When prompted, provide login credentials to # to the user account that is used in your CI and has permissions to publish the package
3. If successful, a line will be added to your `.npmrc` file (`$HOME/.npmrc` on Unix) which looks like: `//repo.vaticle.com/repository/npm-snapshot/:_authToken=NpmToken.00000000-0000-0000-0000-000000000000`. The token is the value of `_authToken`, in this case `NpmToken.00000000-0000-0000-0000-000000000000`.
3. If successful, a line will be added to your `.npmrc` file (`$HOME/.npmrc` on Unix) which looks like: `//npm.cloudsmith.io/typedb/private/:_authToken=NpmToken.00000000-0000-0000-0000-000000000000`. The token is the value of `_authToken`, in this case `NpmToken.00000000-0000-0000-0000-000000000000`.
4. Save the auth token somewhere safe and then delete it from your `.npmrc` file

### Using a UI
Expand Down Expand Up @@ -321,30 +321,6 @@ Execute Packer to perform deployment
| <a id="deploy_packer-target"></a>target | <code>assemble_packer</code> label to be deployed. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |


<a id="deploy_rpm"></a>

## deploy_rpm

<pre>
deploy_rpm(<a href="#deploy_rpm-name">name</a>, <a href="#deploy_rpm-release">release</a>, <a href="#deploy_rpm-snapshot">snapshot</a>, <a href="#deploy_rpm-target">target</a>)
</pre>

Deploy package built with `assemble_rpm` to RPM repository.

Select deployment to `snapshot` or `release` repository with `bazel run //:some-deploy-rpm -- [snapshot|release]


**ATTRIBUTES**


| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="deploy_rpm-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="deploy_rpm-release"></a>release | Remote repository to deploy rpm release to | String | required | |
| <a id="deploy_rpm-snapshot"></a>snapshot | Remote repository to deploy rpm snapshot to | String | required | |
| <a id="deploy_rpm-target"></a>target | <code>assemble_rpm</code> target to deploy | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |


<a id="doxygen_docs"></a>

## doxygen_docs
Expand Down Expand Up @@ -651,36 +627,6 @@ Assemble files for HashiCorp Packer deployment
| <a id="assemble_packer-files"></a>files | Files to include into deployment | <code>{}</code> |


<a id="assemble_rpm"></a>

## assemble_rpm

<pre>
assemble_rpm(<a href="#assemble_rpm-name">name</a>, <a href="#assemble_rpm-package_name">package_name</a>, <a href="#assemble_rpm-spec_file">spec_file</a>, <a href="#assemble_rpm-version_file">version_file</a>, <a href="#assemble_rpm-workspace_refs">workspace_refs</a>, <a href="#assemble_rpm-installation_dir">installation_dir</a>,
<a href="#assemble_rpm-archives">archives</a>, <a href="#assemble_rpm-empty_dirs">empty_dirs</a>, <a href="#assemble_rpm-files">files</a>, <a href="#assemble_rpm-permissions">permissions</a>, <a href="#assemble_rpm-symlinks">symlinks</a>, <a href="#assemble_rpm-tags">tags</a>)
</pre>

Assemble package for installation with RPM

**PARAMETERS**


| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="assemble_rpm-name"></a>name | A unique name for this target. | none |
| <a id="assemble_rpm-package_name"></a>package_name | Package name for built .rpm package | none |
| <a id="assemble_rpm-spec_file"></a>spec_file | The RPM spec file to use | none |
| <a id="assemble_rpm-version_file"></a>version_file | File containing version number of a package. Alternatively, pass --define version=VERSION to Bazel invocation. Not specifying version defaults to '0.0.0' | <code>None</code> |
| <a id="assemble_rpm-workspace_refs"></a>workspace_refs | JSON file with other Bazel workspace references | <code>None</code> |
| <a id="assemble_rpm-installation_dir"></a>installation_dir | directory into which .rpm package is unpacked at installation | <code>None</code> |
| <a id="assemble_rpm-archives"></a>archives | Bazel labels of archives that go into .rpm package | <code>[]</code> |
| <a id="assemble_rpm-empty_dirs"></a>empty_dirs | list of empty directories created at package installation | <code>[]</code> |
| <a id="assemble_rpm-files"></a>files | mapping between Bazel labels of archives that go into .rpm package and their resulting location on .rpm package installation | <code>{}</code> |
| <a id="assemble_rpm-permissions"></a>permissions | mapping between paths and UNIX permissions | <code>{}</code> |
| <a id="assemble_rpm-symlinks"></a>symlinks | mapping between source and target of symbolic links created at installation | <code>{}</code> |
| <a id="assemble_rpm-tags"></a>tags | additional tags passed to all wrapped rules | <code>[]</code> |


Copy link
Member Author

Choose a reason for hiding this comment

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

Removes rpm targets

<a id="assemble_targz"></a>

## assemble_targz
Expand Down
6 changes: 6 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,9 @@ http_archive(

load("@bazel_stardoc//:setup.bzl", "stardoc_repositories")
stardoc_repositories()

# Load @vaticle_bazel_distribution_uploader
load("//common/uploader:deps.bzl", uploader_deps = "deps")
uploader_deps()
load("@vaticle_bazel_distribution_uploader//:requirements.bzl", install_uploader_deps = "install_deps")
install_uploader_deps()
49 changes: 35 additions & 14 deletions apt/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -187,27 +187,25 @@ def assemble_apt(name,


def _deploy_apt_impl(ctx):
_deploy_script = ctx.actions.declare_file(ctx.attr.deploy_script_name)
package_path = ctx.files.target[0].short_path
ctx.actions.expand_template(
template = ctx.file._deployment_script,
output = ctx.outputs.deployment_script,
output = _deploy_script,
substitutions = {
'{snapshot}' : ctx.attr.snapshot,
'{release}' : ctx.attr.release
'{release}' : ctx.attr.release,
'{package_path}' : package_path,
},
is_executable = True
)

symlinks = {
'package.deb': ctx.files.target[0],
}
deployment_lib_files = ctx.attr._deployment_wrapper_lib[DefaultInfo].default_runfiles.files.to_list()
return DefaultInfo(executable = _deploy_script,
runfiles = ctx.runfiles(files=[ctx.files.target[0]] + deployment_lib_files))

return DefaultInfo(executable = ctx.outputs.deployment_script,
runfiles = ctx.runfiles(
files=[ctx.files.target[0]],
symlinks = symlinks))


deploy_apt = rule(
_deploy_apt = rule(
attrs = {
"target": attr.label(
doc = 'assemble_apt label to deploy'
Expand All @@ -220,13 +218,17 @@ deploy_apt = rule(
mandatory = True,
doc = 'Release repository to deploy apt artifact to'
),
"_deployment_wrapper_lib": attr.label(
default = "//common/uploader:uploader",
),
"_deployment_script": attr.label(
allow_single_file = True,
default = "//apt/templates:deploy.py"
),
},
outputs = {
"deployment_script": "%{name}.sh",
"deploy_script_name": attr.string(
mandatory = True,
doc = 'Name of instantiated deployment script'
),
},
implementation = _deploy_apt_impl,
executable = True,
Expand All @@ -235,3 +237,22 @@ deploy_apt = rule(
Select deployment to `snapshot` or `release` repository with `bazel run //:some-deploy-apt -- [snapshot|release]
"""
)

def deploy_apt(name, target, snapshot, release, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

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

This should be able to either deploy to cloudsmith apt (if we use the cloudsmith://... convention you established) or to the previous version using curl.

Same applies to Artifact and anything else using cloudsmith://... endpoint.

The rules should still able to interchange with snapshot (say Docker) and release (DockerHub) right?

deploy_script_target_name = name + "__deploy"
deploy_script_name = deploy_script_target_name + "-deploy.py"

_deploy_apt(
name = deploy_script_target_name,
target = target,
snapshot = snapshot,
release = release,
deploy_script_name = deploy_script_name,
**kwargs
)

native.py_binary(
name = name,
srcs = [deploy_script_target_name],
main = deploy_script_name,
)
27 changes: 12 additions & 15 deletions apt/templates/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,25 @@
import tempfile
from runpy import run_path

import sys, glob
# Prefer using the runfile dependency than system dependency
runfile_deps = [path for path in map(os.path.abspath, glob.glob('external/*/*'))]
sys.path = runfile_deps + sys.path

from common.uploader.uploader import Uploader

parser = argparse.ArgumentParser()
parser.add_argument('repo_type')
args = parser.parse_args()

repo_type_key = args.repo_type

apt_deployments = {
apt_repositories = {
'snapshot' : "{snapshot}",
'release' : "{release}"
}

apt_registry = apt_deployments[repo_type_key]
repo_url = apt_repositories[repo_type_key]

apt_username, apt_password = (
os.getenv('DEPLOY_APT_USERNAME'),
Expand All @@ -61,19 +68,9 @@
'$DEPLOY_APT_PASSWORD env variable'
)

upload_status_code = subprocess.check_output([
'curl',
'--silent',
'--output', '/dev/stderr',
'--write-out', '%{http_code}',
'-u', '{}:{}'.format(apt_username, apt_password),
'-X', 'POST',
'-H', 'Content-Type: multipart/form-data',
'--data-binary', '@package.deb',
apt_registry
]).decode().strip()
package_path = "{package_path}"

if upload_status_code != '201':
raise Exception('upload failed, got HTTP status code {}'.format(upload_status_code))
uploader = Uploader.create(apt_username, apt_password, repo_url)
uploader.apt(package_path)

print('Deployment completed.')
9 changes: 6 additions & 3 deletions artifact/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ def _deploy_artifact_impl(ctx):
symlinks = {
'VERSION': version_file,
}

deployment_lib_files = ctx.attr._deployment_wrapper_lib[DefaultInfo].default_runfiles.files.to_list()
return DefaultInfo(
executable = _deploy_script,
runfiles = ctx.runfiles(
files = files,
files = files + deployment_lib_files,
symlinks = symlinks,
),
)
Expand Down Expand Up @@ -84,6 +84,9 @@ _deploy_artifact = rule(
doc = "The artifact filename, automatic from the target file if not specified",
default = '',
),
"_deployment_wrapper_lib": attr.label(
default = "//common/uploader:uploader",
),
"_deploy_script_template": attr.label(
allow_single_file = True,
default = "//artifact/templates:deploy.py",
Expand Down Expand Up @@ -165,7 +168,7 @@ def artifact_file(name,

http_file(
name = name,
urls = ["{}/{}/{}/{}".format(repository_url, group_name, version, artifact_name)],
urls = ["{}/names/{}/versions/{}/{}".format(repository_url.rstrip("/"), group_name, version, artifact_name)],
Copy link
Member Author

Choose a reason for hiding this comment

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

Broke if the url had a trailing /

downloaded_file_path = artifact_name,
sha = sha,
tags = tags + ["{}={}".format(versiontype, version)],
Expand Down
26 changes: 7 additions & 19 deletions artifact/templates/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,12 @@
import sys
from posixpath import join as urljoin

import glob
# Prefer using the runfile dependency than system dependency
runfile_deps = [path for path in map(os.path.abspath, glob.glob('external/*/*'))]
sys.path = runfile_deps + sys.path

def upload(url, username, password, local_fn, remote_fn):
upload_status_code = sp.check_output([
'curl', '--silent',
'--write-out', '%{http_code}',
'-u', '{}:{}'.format(username, password),
'--upload-file', local_fn,
urljoin(url, remote_fn)
]).decode().strip()

if upload_status_code != '201':
raise Exception('upload of {} failed, got HTTP status code {}'.format(
local_fn, upload_status_code))

from common.uploader.uploader import Uploader

if len(sys.argv) != 2:
raise ValueError('Should pass only <snapshot|release> as arguments')
Expand Down Expand Up @@ -75,9 +67,6 @@ def upload(url, username, password, local_fn, remote_fn):
.format(version, repo_type, version_snapshot_regex))

filename = '{artifact_filename}'
if filename == '':
filename = os.path.basename('{artifact_path}')

filename = filename.format(version = version)

base_url = None
Expand All @@ -86,6 +75,5 @@ def upload(url, username, password, local_fn, remote_fn):
else:
base_url = '{snapshot}'

dir_url = '{base_url}/{artifact_group}/{version}'.format(version=version, base_url=base_url)

upload(dir_url, username, password, '{artifact_path}', filename)
uploader = Uploader.create(username, password, base_url)
uploader.artifact("{artifact_group}", version, '{artifact_path}', filename)
24 changes: 6 additions & 18 deletions rpm/BUILD → common/uploader/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,11 @@
# specific language governing permissions and limitations
# under the License.
#
load("@vaticle_bazel_distribution_uploader//:requirements.bzl", cloudsmith_requirement = "requirement")

load("@bazel_skylib//:bzl_library.bzl", "bzl_library")

bzl_library(
name = "lib",
srcs = [
"rules.bzl",
"@rules_pkg//:rpm.bzl",
],
deps = [
"@rules_pkg//doc_build:rules_pkg_lib",
],
visibility = ["//visibility:public"]
)

py_binary(
name = "generate_spec_file",
srcs = ["generate_spec_file.py"],
visibility = ["//visibility:public"]
py_library(
name = "uploader",
srcs = glob(["*.py"]),
deps = [cloudsmith_requirement("requests")],
visibility = ["//visibility:public"],
)
Empty file added common/uploader/__init__.py
Empty file.
Loading