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 the new auto-release CircleCI Release #43

Merged
merged 57 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
ecffa72
put back the circle ci config
noklam Jun 28, 2022
79df35b
initial setup for datasets cI
noklam Jun 28, 2022
009c3d6
Add window config
noklam Jun 28, 2022
6284409
dummy changes to trigger CI
noklam Jun 28, 2022
a55ff3d
Bug fix the path-filtering, wrong repository
noklam Jun 28, 2022
5e11bd6
Merge branch 'main' of github.com:kedro-org/kedro-plugins into feat/c…
noklam Jun 28, 2022
11a6a25
More attempts to fix CI - wish I can test locally
noklam Jun 28, 2022
3616dda
Need to cd to the plugins directory before install
noklam Jun 28, 2022
6c79e13
Add window setup for tensorflow test
noklam Jun 28, 2022
77f4566
fixing Spark related test
noklam Jun 28, 2022
63f0002
Fix config
noklam Jun 28, 2022
d3fa5b5
Trigger CI
noklam Jun 28, 2022
fffdec9
reverse the boolean condition...
noklam Jun 28, 2022
935af8c
fix conda env
noklam Jun 28, 2022
ee6581f
Fix Window Test and some linting
noklam Jun 29, 2022
e4a0e54
fix coverage issue
noklam Jun 30, 2022
b857f20
add snippets to check env variable
noklam Jun 30, 2022
8afecfb
Comment out invalid release config for testing
noklam Jun 30, 2022
9c20426
testing
noklam Jun 30, 2022
42258b8
use older python syntax
noklam Jun 30, 2022
bc3c510
remove auto-release change & split PR
noklam Jun 30, 2022
e53ab6f
remove empty lines
noklam Jun 30, 2022
eb6ade0
add CI scripts
noklam Jul 4, 2022
315d236
Revert "add CI scripts"
noklam Jul 4, 2022
547b938
add test to cover loading csv in remote storage
noklam Jul 4, 2022
4ee29fe
Revert "add test to cover loading csv in remote storage"
noklam Jul 4, 2022
2a0ee5b
add build scripts
noklam Jul 4, 2022
7ac9451
update file for permission issue
noklam Jul 5, 2022
cea2141
setup env
noklam Jul 5, 2022
8914067
update config
noklam Jul 5, 2022
23b74b8
Fix broken path
noklam Jul 5, 2022
1ff22b5
update requirements
noklam Jul 5, 2022
15a875d
bug fix
noklam Jul 5, 2022
52c69d7
Make the logging niceer
noklam Jul 5, 2022
55d75f8
update parameter in circleci config
noklam Jul 5, 2022
aeb5249
add condition to trigger main_updated so it won't be triggered in a d…
noklam Jul 5, 2022
9e9fa4b
add more logs
noklam Jul 5, 2022
a555187
update condition
noklam Jul 5, 2022
efedb0e
Try trigger release
noklam Jul 5, 2022
afa701a
temporarily turn off the condition since unittest are not passing
noklam Jul 5, 2022
cf2f5a1
fix config
noklam Jul 5, 2022
54a4f05
fix plugin release
noklam Jul 5, 2022
eff737f
Fix the argument for tag name
noklam Jul 5, 2022
711a7e2
tidy out the config a little bit
noklam Jul 5, 2022
6df8cc8
more bug fix
noklam Jul 5, 2022
6795635
fix pypi folder
noklam Jul 6, 2022
2aaa207
remove the TWINE_REPOSITORY_URL argument
noklam Jul 6, 2022
0eb5611
update the CI config
noklam Jul 6, 2022
a0b5efe
trigger a proper release
noklam Jul 6, 2022
fa9395e
fix config
noklam Jul 6, 2022
ebbe3ac
Merge branch 'main' into feat/refactor-auto-release
noklam Jul 7, 2022
55a57e6
add dummy e2etest
noklam Jul 7, 2022
40ea125
add comments
noklam Jul 7, 2022
b802213
fix lint
noklam Jul 7, 2022
022bbe1
format nicer
noklam Jul 7, 2022
d036af2
Clean up for review
noklam Jul 7, 2022
ce5cbf2
apply review comments
noklam Jul 12, 2022
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
8 changes: 8 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
version: 2.1

parameters:
Copy link
Member

Choose a reason for hiding this comment

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

Why do you need these parameters here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a CircleCI thing, otherwise, it will just throw an error. We called these 2 parameters in the POST request.

release_package:
type: string
default: ""
release_version:
type: string
default: ""

setup: true

# the path-filtering orb is required to continue a pipeline based on
Expand Down
145 changes: 141 additions & 4 deletions .circleci/continue_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ parameters:
run-build-kedro-datasets:
type: boolean
default: false
release_package:
type: string
default: ""
release_version:
type: string
default: ""

commands:
setup_conda:
Expand Down Expand Up @@ -297,12 +303,101 @@ jobs:
name: Run unit tests without spark sequentially
command: conda activate kedro_plugins; make test-no-spark-sequential

sync:
parameters:
python_version:
type: string
docker:
# https://circleci.com/docs/2.0/circleci-images/#circleci-base-image
- image: cimg/base:2020.01
steps:
- checkout
- add_ssh_keys
- run:
name: Set git email and name
command: |
git config --global user.email "[email protected]"
git config --global user.name "Kedro"
# - run:
# name: Trigger Read The Docs build
# command: ./tools/circleci/rtd-build.sh ${RTD_TOKEN} latest
- setup_conda:
python_version: <<parameters.python_version>>
- run:
name: Maybe trigger the release workflow
command: |
conda activate kedro_plugins;
pip install requests
./tools/circleci/circleci_release.py


# This is effectively just a combination of the lint, unit_tests and e2e_tests jobs.
# It's used to check that the nightly docker image is working ok and before publishing a release.
build_package:
parameters:
python_version:
type: string
machine:
image: ubuntu-2004:202201-02
docker_layer_caching: true
steps:
- setup:
python_version: <<parameters.python_version>> # Just need one Python version here
plugin: <<pipeline.parameters.release_package>>
- run:
name: Run linters
command: export plugin=<<pipeline.parameters.release_package>>; make lint
- unless:
condition:
equal: ["3.10", <<parameters.python_version>>]
steps:
- run:
name: Run unit tests in parallel
command: export plugin=<<pipeline.parameters.release_package>>; make test
- when:
condition:
equal: [ "3.10", <<parameters.python_version>> ]
steps:
- run:
name: Run unit tests sequentially
command: export plugin=<<pipeline.parameters.release_package>>; make test-sequential
- run:
name: Run e2e tests
command: export plugin=<<pipeline.parameters.release_package>>; make e2e-tests

publish_package:
machine:
image: ubuntu-2004:202201-02
docker_layer_caching: true
steps:
- run:
name: Print the release package and version
command: |
echo "Release package: <<pipeline.parameters.release_package>> <<pipeline.parameters.release_version>>"
- setup:
python_version: "3.8" # Just need one Python version here
plugin: <<pipeline.parameters.release_package>> # From circle_release.py
- add_ssh_keys
- run:
name: Tag and publish release on Github
command: ./tools/circleci/github_release.py <<pipeline.parameters.release_package>> <<pipeline.parameters.release_version>>
- run:
name: Publish to PyPI
command: |
export plugin=<<pipeline.parameters.release_package>>
make package
make pypi


workflows:
# when pipeline parameter, run-build-kedro-telemetry is true, the
# kedro-telemetry job is triggered.
kedro-telemetry:
when: <<pipeline.parameters.run-build-kedro-telemetry>>
when:
and:
- <<pipeline.parameters.run-build-kedro-telemetry>>
- not: <<pipeline.parameters.release_package>>
- not: <<pipeline.parameters.release_version>>
jobs:
- unit_tests:
plugin: "kedro-telemetry"
Expand All @@ -319,7 +414,11 @@ workflows:
# when pipeline parameter, run-build-kedro-docker is true, the
# kedro-docker job is triggered.
kedro-docker:
when: <<pipeline.parameters.run-build-kedro-docker>>
when:
and:
- <<pipeline.parameters.run-build-kedro-docker>>
- not: <<pipeline.parameters.release_package>>
- not: <<pipeline.parameters.release_version>>
jobs:
- unit_tests:
plugin: "kedro-docker"
Expand All @@ -341,7 +440,11 @@ workflows:
# when pipeline parameter, run-build-kedro-airflow is true, the
# kedro-airflow job is triggered.
kedro-airflow:
when: <<pipeline.parameters.run-build-kedro-airflow>>
when:
and:
- <<pipeline.parameters.run-build-kedro-airflow>>
- not: <<pipeline.parameters.release_package>>
- not: <<pipeline.parameters.release_version>>
jobs:
- unit_tests:
plugin: "kedro-airflow"
Expand All @@ -363,7 +466,11 @@ workflows:
# when pipeline parameter, run-build-kedro-datasets is true, the
# kedro-datasets job is triggered.
kedro-datasets:
when: <<pipeline.parameters.run-build-kedro-datasets>>
when:
and:
- <<pipeline.parameters.run-build-kedro-datasets>>
- not: <<pipeline.parameters.release_package>>
- not: <<pipeline.parameters.release_version>>
jobs:
- unit_tests:
plugin: "kedro-datasets"
Expand All @@ -377,3 +484,33 @@ workflows:
python_version: ["3.7", "3.8", "3.9", "3.10"]
- lint:
plugin: "kedro-datasets"

# For release
main_updated:
when:
and:
- not: <<pipeline.parameters.release_package>>
- not: <<pipeline.parameters.release_version>>
jobs:
- sync:
filters:
branches:
only: main
matrix:
# We just need one Python enviornment to trigger the job
parameters:
python_version: ["3.8"]

package_release:
when:
and:
- <<pipeline.parameters.release_package>>
- <<pipeline.parameters.release_version>>
jobs:
- build_package:
matrix:
parameters:
python_version: ["3.7", "3.8", "3.9", "3.10"]
- publish_package:
requires:
- build_package
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package:
python setup.py sdist bdist_wheel

pypi:
python -m pip install twine -U
python -m twine upload $(plugin)/dist/*

install: package
Expand All @@ -18,6 +19,9 @@ lint:
test:
cd $(plugin) && pytest tests --cov-config pyproject.toml --numprocesses 4 --dist loadfile

test-sequential:
cd $(plugin) && pytest tests --cov-config pyproject.toml

e2e-tests:
cd $(plugin) && behave

Expand Down
1 change: 1 addition & 0 deletions kedro-datasets/features/steps/dummy.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# A dummy file to keep CI behave correctly
5 changes: 1 addition & 4 deletions kedro-datasets/kedro_datasets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
"""``kedro_datasets`` is where you can find all of Kedro's data connectors."""

__version__ = "0.0.2"


# todo: remove this before merge Trigger CI with file changes
__version__ = "0.0.4"
2 changes: 1 addition & 1 deletion kedro-datasets/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ min-public-methods = 1
[tool.coverage.report]
fail_under = 100
show_missing = true
omit = ["tests/*"]
omit = ["tests/*", "kedro_datasets/datasets/holoviews/*"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Carries from kedro

exclude_lines = ["pragma: no cover", "raise NotImplementedError"]

[tool.pytest.ini_options]
Expand Down
75 changes: 75 additions & 0 deletions tools/circleci/circleci_release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""
CircleCI pipeline to check if it needs to trigger a release
"""

import os

import requests
from requests.structures import CaseInsensitiveDict

from utils.check_no_version_pypi import check_no_version_pypi
from utils.package_version import get_package_version

PACKAGE_PATHS = (
"kedro-datasets/kedro_datasets",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In theory, we can just use kedro-datasets and parse it, but I am not sure if this is a convention. So I just keep the longer path here, not too important anyway.

"kedro-telemetry/kedro_telemetry",
"kedro-airflow/kedro_airflow",
"kedro-docker/kedro_docker",
)
PROJECT_SLUG = "github/kedro-org/kedro-plugins"
# CIRCLE_BRANCH = "feat/cicd-auto-release"
CIRCLE_BRANCH = os.environ.get("CIRCLE_BRANCH")


def circleci_release(project_slug, payload, circle_endpoint, circle_release_token):
"""Trigging the CircleCI Release Pipeline"""
# See https://circleci.com/docs/2.0/api-developers-guide
print("Starting the CircleCI Release Pipeline")
CIRCLE_ENDPOINT = f"https://circleci.com/api/v2/project/{project_slug}/pipeline"

headers = CaseInsensitiveDict()
headers["Content-Type"] = "application/json"
headers["Circle-Token"] = circle_release_token

resp = requests.post(circle_endpoint, headers=headers, json=payload)
print(f"Status Code: {resp.status_code}")
if resp.status_code == 201:
print("Creating CircleCI Pipeline successfully")
print(resp.content)
else:
print("Failed to create CircleCI Pipeline")
Copy link
Member

Choose a reason for hiding this comment

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

Do we need any more info here? Error code or something like that to help us figure out what went wrong?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with Merel, maybe put the response code in the print statement as well.

return resp


if __name__ == "__main__":
"""Trigger the CircleCI Release Process"""
from pathlib import Path

# Personal API Tokens - https://circleci.com/docs/managing-api-tokens
CIRCLE_RELEASE_TOKEN = os.environ.get("CIRCLE_RELEASE_TOKEN")
if not CIRCLE_RELEASE_TOKEN:
raise ValueError("CIRCLE_RELEASE_TOKEN is not defined as envionrmnet variable.")

base_path = Path()
# Loop for all 4 repositories
for package_path in PACKAGE_PATHS:
package_name, _ = package_path.split("/")
package_version = get_package_version(base_path, package_path)
pypi_endpoint = f"https://pypi.org/pypi/{package_name}/{package_version}/json/"
circleci_endpoint = (
f"https://circleci.com/api/v2/project/{PROJECT_SLUG}/pipeline"
)
payload = {
"branch": CIRCLE_BRANCH,
"parameters": {
"release_package": package_name,
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 used to check the version twice in two different jobs, I think it's better to keep a single source of truth and just pass this information in the requests.

"release_version": package_version,
},
}

print(package_name, package_version)
if check_no_version_pypi(pypi_endpoint, package_name, package_version):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Everytime main is updated, it will check all repositories and see if there is a need to do a release. So it is possible that it triggers more than 1 release job (for different repository) but in practice, we shouldn't have one commit changing 2 different repositories.

circleci_release(
PROJECT_SLUG, payload, circleci_endpoint, CIRCLE_RELEASE_TOKEN
)
52 changes: 52 additions & 0 deletions tools/circleci/github_release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3
import os
import sys

import requests
from requests.structures import CaseInsensitiveDict

GITHUB_USER = "kedro-org"
GITHUB_REPO = "kedro-plugins"
# On GitHub select "Settings" > "Developer Setting" -> "Personal access Token""
GITHUB_TAGGING_TOKEN = os.environ.get("GITHUB_TAGGING_TOKEN")


def github_release(
package_name,
version,
github_user=GITHUB_USER,
github_repo=GITHUB_REPO,
github_tagging_token=GITHUB_TAGGING_TOKEN,
):
"""Trigger the GitHub Release to create artifacts and tags"""
print("Starting GitHub Release")

github_endpoint = (
f"https://api.github.com/repos/{github_user}/{github_repo}/releases"
)
payload = {
"tag_name": f"{package_name}-{version}", # kedro-datasets 0.0.1
"target_commitish": "main",
"name": f"{version}",
"body": f"Release {version}",
"draft": False,
"prerelease": False,
}

headers = CaseInsensitiveDict()
headers["Content-Type"] = "application/json"
headers["Authorization"] = f"token {github_tagging_token}"
resp = requests.post(github_endpoint, headers=headers, json=payload)
if resp.status_code == 200:
print("Create GitHub release successfully")
print(resp.content)
else:
print("Failed to create Github release")
print(resp.content)
return resp


if __name__ == "__main__":
package_name = sys.argv[1]
package_version = sys.argv[2]
res = github_release(package_name, package_version)
13 changes: 13 additions & 0 deletions tools/circleci/utils/check_no_version_pypi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import requests


def check_no_version_pypi(pypi_endpoint, package_name, package_version):
print("Check if {package_name} {package_version} is on pypi")
response = requests.get(pypi_endpoint)
if response.status_code == 404:
# Not exist on Pypi - do release
print(f"Starting the release of {package_name} {package_version}")
return True
else:
print(f"Skipped: {package_name} {package_version} already exists on PyPI")
return False
Loading