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

Change nightly call to support new API tokens #1206

Draft
wants to merge 7 commits into
base: jrivero/remove_the_longest_token_ever
Choose a base branch
from
Draft
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
5 changes: 4 additions & 1 deletion check_releasepy.bash
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/bin/bash -e

export _RELEASEPY_DEBUG=1
export _RELEASEPY_TEST_CREDENTIALS=1

test_dir=$(mktemp -d)
export _RELEASEPY_TEST_RELEASE_REPO="${test_dir}/test-release"
Expand All @@ -27,6 +26,7 @@ exec_releasepy_test()
./release.py \
--dry-run \
--no-sanity-checks \
--auth user:fake \
gz-foo 1.2.3 ${test_params}
}

Expand All @@ -37,6 +37,7 @@ exec_ignition_releasepy_test()
./release.py \
--dry-run \
--no-sanity-checks \
--auth user:fake \
ign-foo 1.2.3 ${test_params}
}

Expand All @@ -47,6 +48,7 @@ exec_ignition_gazebo_releasepy_test()
./release.py \
--dry-run \
--no-sanity-checks \
--auth user:fake \
ign-gazebo 1.2.3 ${test_params}
}

Expand All @@ -56,6 +58,7 @@ exec_releasepy_with_real_gz()
./release.py \
--dry-run \
--no-sanity-checks \
--auth user:fake \
--source-repo-uri http://github.com/gazebosim/gz-common \
--source-repo-existing-ref http://github.com/gazebosim/gz-common/foo-tag \
"${gz_pkg}" "${major_version}.x.y"
Expand Down
19 changes: 19 additions & 0 deletions jenkins-scripts/dsl/_configs_/GitHubCredentials.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package _configs_

import javaposse.jobdsl.dsl.Job

class GitHubCredentials
{
static void createOsrfbuildToken(Job job)
{
job.with
{
wrappers {
// Credential name needs to be in sync with provision code at infra/osrf-chef repo
credentialsBinding {
usernamePassword('OSRFBUILD_USER', 'OSRFBUILD_TOKEN', 'github-osrfbuild-credentials')
}
}
}
}
}
11 changes: 7 additions & 4 deletions jenkins-scripts/dsl/ignition_collection.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ nightly_collection = gz_collections_yaml.collections

def nightly_scheduler_job = job("ignition-${gz_nightly}-nightly-scheduler")
OSRFUNIXBase.create(nightly_scheduler_job)
GitHubCredentials.createOsrfbuildToken(nightly_scheduler_job)

nightly_scheduler_job.with
{
Expand Down Expand Up @@ -190,8 +191,6 @@ nightly_scheduler_job.with
steps {
shell("""\
#!/bin/bash -xe
set +x # keep password secret
PASS=\$(cat \$HOME/build_pass)

dry_run_str=""
if \$DRY_RUN; then
Expand Down Expand Up @@ -239,9 +238,13 @@ nightly_scheduler_job.with
src_branch="main"
fi

set +x # safeguard keep password secret
echo "releasing \${n} (from branch \${src_branch})"
python3 ./scripts/release.py \${dry_run_str} "\${n}" nightly "\${PASS}" --release-repo-branch main --nightly-src-branch \${src_branch} --upload-to-repo nightly > log || echo "MARK_AS_UNSTABLE"
echo " - done"
python3 ./scripts/release.py \${dry_run_str} "\${n}" nightly \
--auth "{OSRFBUILD_USER}:\${OSRFBUILD_TOKEN}"' \
--release-repo-branch main --nightly-src-branch \${src_branch} --upload-to-repo nightly > log || echo "MARK_AS_UNSTABLE"
set -e
echo " - done (log is available)"
done

""".stripIndent())
Expand Down
60 changes: 60 additions & 0 deletions jenkins-scripts/dsl/test.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,63 @@ outdated_job_runner.with
systemGroovyCommand(readFileFromWorkspace('scripts/jenkins-scripts/tools/outdated-job-runner.groovy'))
}
}

// --------------------------------------------------------------------
def test_credentials_token_job = job("_test_job_osrfbuild-credentials-token_from_dsl")
OSRFBase.create(test_credentials_token_job)
GitHubCredentials.createOsrfbuildToken(test_credentials_token_job)
test_credentials_token_job.with
{
label "docker"

steps {
shell("""\
#!/bin/bash -xe

echo "Testing the login into the Jenkins server:"
curl --silent --fail --write '\\nReturn code: %{http_code}\\n' --user "\${OSRFBUILD_USER}:\${OSRFBUILD_TOKEN}" \${JENKINS_URL} --output /dev/null
""".stripIndent())

shell("""\
#!/bin/bash -xe

# Check push+commit permissions for osrfbuild by uploading/deleting a
# branch. Note that call to the API for permissions require of admin
# perms that osrfbuild user does not have. Personal tokens don't
# support ssh but https only.

rm -fr homebrew-simulation
git clone https://github.com/\${OSRFBUILD_USER}/homebrew-simulation.git
cd homebrew-simulation
git config user.name \${OSRFBUILD_USER} --replace-all
git config user.email "\${OSRFBUILD_USER}@openrobotics.org" --replace-all
git config url."https://\${OSRFBUILD_USER}:\${OSRFBUILD_TOKEN}@github.com/\${OSRFBUILD_USER}/homebrew-simulation.git".InsteadOf https://github.com/\${OSRFBUILD_USER}/homebrew-simulation.git
git checkout -b _test_job_osrfbuild_
git commit --allow-empty -m "testing commit"
# protect token from errors
git push -u origin _test_job_osrfbuild_ > push_log
git push origin --delete _test_job_osrfbuild_ >> push_log
""".stripIndent())
}

publishers
{
postBuildScripts {
steps {
shell("""\
#!/bin/bash -xe

# remove token after the build ends unconditionally
rm -fr \${WORKSPACE}/homebrew-simulation/.git/config
""".stripIndent())
}

onlyIfBuildSucceeds(false)
onlyIfBuildFails(false)
}
}

wrappers {
preBuildCleanup()
}
}
47 changes: 26 additions & 21 deletions release.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ def parse_args(argv):
parser.add_argument('version', help='which version to release')
parser.add_argument('--dry-run', dest='dry_run', action='store_true', default=False,
help='dry-run; i.e., do actually run any of the commands')
parser.add_argument('--auth', dest='auth_input_arg',
default=None,
help='Explicit jenkins user:token string overriding the jenkins.ini credentials file.')
parser.add_argument('-a', '--package-alias', dest='package_alias',
default=None,
help='different name that we are releasing under')
Expand Down Expand Up @@ -182,12 +185,6 @@ def parse_args(argv):
# BEGIN: Credentials code copied from ros_buildfarm
#
def get_credentials(jenkins_url=None):
try:
if os.environ['_RELEASEPY_TEST_CREDENTIALS']:
return 'fake_user', 'fake_api_token'
except KeyError:
pass

config = ConfigParser()
config_file = get_credential_path()
if not os.path.exists(config_file):
Expand Down Expand Up @@ -382,12 +379,8 @@ def sanity_checks(args, repo_dir):
sanity_check_sdformat_versions(args.package, args.version)
sanity_project_package_in_stable(args.version, args.upload_to_repository)

try:
if os.environ['_RELEASEPY_TEST_CREDENTIALS']:
pass
except KeyError:
check_credentials()
print_success("Jenkins credentials are good")
check_credentials(args.auth_input_arg)
print_success("Jenkins credentials are good")

shutil.rmtree(repo_dir)

Expand Down Expand Up @@ -539,23 +532,33 @@ def generate_source_params(args):

return params

def build_credentials_header():
username, api_token = get_credentials(JENKINS_URL)
if not username:
exit(1)
def build_credentials_header(auth_input_arg = None):
if auth_input_arg:
if len(auth_input_arg.split(':')) != 2:
error("Auth string is not in the form of 'user:token' ")
username, api_token = auth_input_arg.split(':')
else:
username, api_token = get_credentials(JENKINS_URL)
if not username:
exit(1)

return make_headers(basic_auth=f'{username}:{api_token}')

def check_credentials():
def check_credentials(auth_input_arg = None):
http = urllib3.PoolManager()
response = http.request('GET', JENKINS_URL, headers=build_credentials_header())
response = http.request('GET',
JENKINS_URL,
headers=build_credentials_header(auth_input_arg))
if response.status != 200:
print(f"Crendentials error: {response.status}: {response.reason}")
http.clear()
exit(1)

def call_jenkins_build(job_name, params, output_string,
search_description_help):
def call_jenkins_build(job_name,
params,
output_string,
search_description_help,
auth_input_arg = None):
# Only to help user feedback this block
help_url = f'{JENKINS_URL}/job/{job_name}'
if search_description_help:
Expand All @@ -573,7 +576,9 @@ def call_jenkins_build(job_name, params, output_string,
if not DRY_RUN:
http = urllib3.PoolManager()
try :
response = http.request('POST', url , headers=build_credentials_header())
response = http.request('POST',
url ,
headers=build_credentials_header(auth_input_arg))
# 201 code is "created", it is the expected return of POST
if response.status != 201:
print(f"Error {response.status}: {response.reason}")
Expand Down
Loading