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

support github actions as a CI provider #1461

Merged
merged 4 commits into from
Mar 11, 2021
Merged
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
95 changes: 94 additions & 1 deletion conda_smithy/configure_feedstock.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,18 @@ def _render_ci_provider(
config,
forge_config,
)
for channel_target in migrated_combined_variant_spec.get(
"channel_targets", []
):
if (
channel_target.startswith("conda-forge ")
and provider_name == "github_actions"
):
raise RuntimeError(
"Using github_actions as the CI provider inside "
"conda-forge github org is not allowed in order "
"to avoid a denial of service for other infrastructure."
)

# AFAIK there is no way to get conda build to ignore the CBC yaml
# in the recipe. This one can mess up migrators applied with local
Expand Down Expand Up @@ -1151,6 +1163,75 @@ def render_appveyor(jinja_env, forge_config, forge_dir, return_metadata=False):
)


def _github_actions_specific_setup(
jinja_env, forge_config, forge_dir, platform
):

build_setup = _get_build_setup_line(forge_dir, platform, forge_config)

if platform == "linux":
yum_build_setup = generate_yum_requirements(forge_config, forge_dir)
if yum_build_setup:
forge_config["yum_build_setup"] = yum_build_setup

forge_config = deepcopy(forge_config)
forge_config["build_setup"] = build_setup

platform_templates = {
"linux": [
".scripts/run_docker_build.sh",
".scripts/build_steps.sh",
],
"osx": [
".scripts/run_osx_build.sh",
],
}
template_files = platform_templates.get(platform, [])

_render_template_exe_files(
forge_config=forge_config,
jinja_env=jinja_env,
template_files=template_files,
forge_dir=forge_dir,
)


def render_github_actions(
jinja_env, forge_config, forge_dir, return_metadata=False
):
target_path = os.path.join(
forge_dir, ".github", "workflows", "conda-build.yml"
)
template_filename = "github-actions.tmpl"
fast_finish_text = ""

(
platforms,
archs,
keep_noarchs,
upload_packages,
) = _get_platforms_of_provider("github_actions", forge_config)

logger.debug("github platforms retreived")

remove_file_or_dir(target_path)
return _render_ci_provider(
"github_actions",
jinja_env=jinja_env,
forge_config=forge_config,
forge_dir=forge_dir,
platforms=platforms,
archs=archs,
fast_finish_text=fast_finish_text,
platform_target_path=target_path,
platform_template_file=template_filename,
platform_specific_setup=_github_actions_specific_setup,
keep_noarchs=keep_noarchs,
upload_packages=upload_packages,
return_metadata=return_metadata,
)


def _azure_specific_setup(jinja_env, forge_config, forge_dir, platform):

build_setup = _get_build_setup_line(forge_dir, platform, forge_config)
Expand Down Expand Up @@ -1459,6 +1540,7 @@ def _load_forge_config(forge_dir, exclusive_config_file):
"drone": {},
"travis": {},
"circle": {},
"github_actions": {},
"config_version": "2",
"appveyor": {"image": "Visual Studio 2017"},
"azure": {
Expand Down Expand Up @@ -1948,7 +2030,14 @@ def main(
config = _load_forge_config(forge_dir, exclusive_config_file)
config["feedstock_name"] = os.path.basename(forge_dir)

for each_ci in ["travis", "circle", "appveyor", "drone"]:
for each_ci in [
"travis",
"circle",
"appveyor",
"drone",
"azure",
"github_actions",
]:
if config[each_ci].pop("enabled", None):
warnings.warn(
"It is not allowed to set the `enabled` parameter for `%s`."
Expand Down Expand Up @@ -1991,6 +2080,10 @@ def main(
render_drone(env, config, forge_dir, return_metadata=True)
)
logger.debug("drone rendered")
render_info.append(
render_github_actions(env, config, forge_dir, return_metadata=True)
)
logger.debug("github_actions rendered")
# put azure first just in case
tmp = render_info[0]
render_info[0] = render_info[-2]
Expand Down
133 changes: 133 additions & 0 deletions conda_smithy/templates/github-actions.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# This file was generated automatically from conda-smithy. To update this configuration,
# update the conda-forge.yml and/or the recipe/meta.yaml.
# -*- mode: yaml -*-

{%- set platformset = [] %}
{%- for data in configs %}
{%- set pfarchless = data.build_platform.split('-')[0] %}
{%- if pfarchless not in platformset %}
{%- do platformset.append(pfarchless) %}
{%- endif %}
{%- endfor %}

name: Build conda package
on: [push, pull_request]

jobs:
build:
name: {% raw %}${{ matrix.CONFIG }}{% endraw %}
runs-on: {% raw %}${{ matrix.os }}{% endraw %}-latest
strategy:
fail-fast: false
matrix:
include:
{%- for data in configs %}
- CONFIG: {{ data.config_name }}
UPLOAD_PACKAGES: {{ data.upload }}
{%- if data.build_platform.startswith("osx") %}
os: macos
{%- elif data.build_platform.startswith("linux") %}
DOCKER_IMAGE: {{ data.config["docker_image"][-1] }}
os: ubuntu
{%- elif data.build_platform.startswith("win") %}
os: windows
{%- endif %}
{%- endfor %}
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Build on Linux
if: matrix.os == 'ubuntu'
env:
CONFIG: {% raw %}${{ matrix.CONFIG }}{% endraw %}
UPLOAD_PACKAGES: {% raw %}${{ matrix.UPLOAD_PACKAGES }}{% endraw %}
DOCKERIMAGE: {% raw %}${{ matrix.DOCKERIMAGE }}{% endraw %}
CI: github_actions
{%- if upload_on_branch %}
UPLOAD_ON_BRANCH: {{ upload_on_branch }}
{%- endif %}
{%- if docker.run_args is defined %}
CONDA_FORGE_DOCKER_RUN_ARGS: "{{ docker.run_args }}"
{%- endif %}
{%- for secret in secrets %}
{{ secret }}: {% raw %}${{{% endraw %} secrets.{{ secret }} {% raw %}}}{% endraw %}
{%- endfor %}
shell: bash
run: |
docker run --rm --privileged multiarch/qemu-user-static:register --reset --credential yes
export FEEDSTOCK_NAME="$(basename $GITHUB_REPOSITORY)"
export GIT_BRANCH="$(basename $GITHUB_REF)"
./.scripts/run_docker_build.sh

- name: Build on macOS
if: matrix.os == 'macos'
env:
CONFIG: {% raw %}${{ matrix.CONFIG }}{% endraw %}
UPLOAD_PACKAGES: {% raw %}${{ matrix.UPLOAD_PACKAGES }}{% endraw %}
CI: github_actions
{%- if upload_on_branch %}
UPLOAD_ON_BRANCH: {{ upload_on_branch }}
{%- endif %}
{%- for secret in secrets %}
{{ secret }}: {% raw %}${{{% endraw %} secrets.{{ secret }} {% raw %}}}{% endraw %}
{%- endfor %}
shell: bash
run: |
export FEEDSTOCK_NAME="$(basename $GITHUB_REPOSITORY)"
export GIT_BRANCH="$(basename $GITHUB_REF)"
./.scripts/run_osx_build.sh

{%- for choco_pkg in choco %}
- name: "Install Chocolatey Package: {{ choco_pkg }}"
if matrix.os == 'windows'
run: |
choco install {{ choco_pkg }} -fdv -y --debug
{% endfor %}

- name: Install Miniconda for windows
uses: conda-incubator/setup-miniconda@v2
with:
miniconda-version: latest
if: matrix.os == 'windows'

- name: Build on windows
shell: cmd
run: |
call activate base
conda.exe install -c conda-forge 'python=3.6' conda-build conda "{{ remote_ci_setup }}" pip {{- ' boa' if build_with_mambabuild else '' }}
{%- if local_ci_setup %}
conda.exe uninstall --quiet --yes --force "{{ remote_ci_setup }}"
pip install --no-deps ".\{{ recipe_dir }}\."
{%- endif %}
setup_conda_rc .\ ".\{{ recipe_dir }}" .\.ci_support\%CONFIG%.yaml
{% if build_setup -%}
{{ build_setup.replace("\n", "\n ").rstrip() }}
{%- endif %}

{%- if build_with_mambabuild %}
conda.exe mambabuild "{{ recipe_dir }}" -m .ci_support\%CONFIG%.yaml
exit 1
{%- else %}
conda.exe build "{{ recipe_dir }}" -m .ci_support\%CONFIG%.yaml
{%- endif %}
set "FEEDSTOCK_NAME=%GITHUB_REPOSITORY:*/=%"
set "GIT_BRANCH=%GITHUB_REF:*/=%"
{%- if conda_forge_output_validation %}
validate_recipe_outputs "%FEEDSTOCK_NAME%"
{%- endif %}
if %UPLOAD_PACKAGES% == "True" (
upload_package {% if conda_forge_output_validation %}--validate --feedstock-name="%FEEDSTOCK_NAME%"{% endif %}{% if private_upload %} --private{% endif %} .\ ".\{{ recipe_dir }}" .ci_support\%CONFIG%.yaml
)
env:
PYTHONUNBUFFERED: 1
CONFIG: {% raw %}${{ matrix.CONFIG }}{% endraw %}
CI: github_actions
UPLOAD_PACKAGES: {% raw %}${{ matrix.UPLOAD_PACKAGES }}{% endraw %}
{%- if upload_on_branch %}
UPLOAD_ON_BRANCH: {{ upload_on_branch }}
{%- endif %}
{%- for secret in secrets %}
{{ secret }}: {% raw %}${{{% endraw %} secrets.{{ secret }} {% raw %}}}{% endraw %}
if: matrix.os == 'windows'
{%- endfor %}
25 changes: 25 additions & 0 deletions news/github_actions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**Added:**

* Added support for Github Actions as a CI provider. Provider name to use in conda-forge.yml
is `github_actions`. Note that Github Actions cannot be enabled as a CI provider for conda-forge
github organization to prevent a denial of service for other infrastructure.

**Changed:**

* <news item>

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
21 changes: 21 additions & 0 deletions tests/test_configure_feedstock.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,27 @@ def test_py_matrix_on_circle(py_recipe, jinja_env):
assert len(os.listdir(matrix_dir)) == 2


def test_py_matrix_on_github(py_recipe, jinja_env):
py_recipe.config["provider"]["linux"] = "github_actions"

cnfgr_fdstk.render_github_actions(
jinja_env=jinja_env,
forge_config=py_recipe.config,
forge_dir=py_recipe.recipe,
)
# this configuration should be run
assert py_recipe.config["github_actions"]["enabled"]
matrix_dir = os.path.join(py_recipe.recipe, ".ci_support")
assert os.path.isdir(matrix_dir)
# single matrix entry - readme is generated later in main function
assert len(os.listdir(matrix_dir)) == 2
assert os.path.exists(
os.path.join(
py_recipe.recipe, ".github", "workflows", "conda-build.yml"
)
)


def test_py_matrix_on_azure(py_recipe, jinja_env):
cnfgr_fdstk.render_azure(
jinja_env=jinja_env,
Expand Down