Skip to content
Open
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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,18 @@ The **subject line templates** support the use of the following variables only.

**Note**: If your project uses multiple GitHub repositories, we recommend using the `repository` variable to let people know which repo the email relates to. If your project has a single repo or does not use GitHub integration much (or at all), you can omit that variable.

<h3 id="immutable_releases">Immutable Releases</h3>

Immutable GitHub releases make the release Git tag and the release assets immutable.
See [GitHub Docs](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases).

To enable immutable GitHub releases:
~~~yaml
github:
# The default is false
immutable_releases: true
~~~

<h3 id="default_branch">Default branch</h3>

To change the default GitHub repository branch (which is the landing branch when users browse to `github.com/apache/<repository>` and the default branch pull requests are initially based on, etc.) create an INFRA Jira ticket. If you are renaming the default branch and the new default branch does not yet exist, you can ask Infra to rename the branch at the same time. Include a **link** to the mailing list thread where the change of the default was agreed.
Expand Down
3 changes: 3 additions & 0 deletions asfyaml/feature/github/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class ASFGitHubFeature(ASFYamlFeature, name="github"):
# GitHub Pages: branch (can be default or gh-pages) and path (can be /docs or /)
strictyaml.Optional("ghp_branch"): strictyaml.Str(),
strictyaml.Optional("ghp_path", default="/docs"): strictyaml.Str(),
# GitHub Immutable Releases
strictyaml.Optional("immutable_releases"): strictyaml.Bool(),
# Branch protection rules - TODO: add actual schema
strictyaml.Optional("protected_branches"): asfyaml.validators.EmptyValue()
| strictyaml.MapPattern(
Expand Down Expand Up @@ -255,6 +257,7 @@ def run(self):
autolink,
features,
branch_protection,
immutable_releases,
pull_requests,
merge_buttons,
pages,
Expand Down
53 changes: 53 additions & 0 deletions asfyaml/feature/github/immutable_releases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

"""Settings related to GitHub Immutable Releases"""

from github.GithubObject import NotSet, is_defined
from typing import TYPE_CHECKING
from . import directive, ASFGitHubFeature

if TYPE_CHECKING:
from github.Requester import Requester


@directive
def immutable_releases(self: ASFGitHubFeature):
immutable_releases_setting = self.yaml.get("immutable_releases", NotSet)
enable = immutable_releases_setting is True if is_defined(immutable_releases_setting) else False
print(f"GitHub immutable releases shall be {'enabled' if enable else 'disabled'}")

url = f"/repos/{self.repository.org_id}/{self.repository.name}/immutable-releases"

if not self.noop("immutable_releases"):
requester: Requester = self.ghrepo.requester
is_enabled_status, _, _ = requester.requestJson("GET", url)
# HTTP status code 404 means that immutable releases are not enabled.
# See https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#check-if-immutable-releases-are-enabled-for-a-repository
is_enabled = is_enabled_status == 200
print(f"GitHub immutable releases are currently {'enabled' if is_enabled else 'disabled'}")

if is_enabled != enable:
if enable:
# https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#enable-immutable-releases
status, _, _ = requester.requestJson("PUT", url)
else:
# https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#disable-immutable-releases
status, _, _ = requester.requestJson("DELETE", url)
assert status == 204, f"Failed to set immutable releases to {enable}"

print(f"GitHub immutable releases are now {'enabled' if enable else 'disabled'}")
2 changes: 2 additions & 0 deletions asfyaml/feature/pelican.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
CI_HOSTNAME = "ci2.apache.org"
CI_HOSTNAME_TEST = "ci2-test.apache.org"


class ASFPelicanFeature(ASFYamlFeature, name="pelican", env="production", priority=4):
schema = strictyaml.Map(
{
Expand Down Expand Up @@ -103,6 +104,7 @@ def run(self):
print(payload)
print("Done!")


class ASFPelicanTestFeature(ASFYamlFeature, name="pelicantest", env="citest", priority=3):
schema = strictyaml.Map(
{
Expand Down
63 changes: 63 additions & 0 deletions tests/github_immutable_releases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

"""Unit tests for .asf.yaml GitHub pull request features"""

from helpers import YamlTest
import asfyaml.asfyaml
import asfyaml.dataobjects

# Set .asf.yaml to debug mode
asfyaml.asfyaml.DEBUG = True


immutable_releases_enabled = YamlTest(
None,
None,
"""
github:
immutable_releases: true
""",
)


immutable_releases_disabled = YamlTest(
None,
None,
"""
github:
immutable_releases: false
""",
)


def test_immutable_releases(test_repo: asfyaml.dataobjects.Repository):
print("[github] Testing immutable releases")

tests_to_run = (
immutable_releases_enabled,
immutable_releases_disabled,
)

for test in tests_to_run:
with test.ctx():
a = asfyaml.asfyaml.ASFYamlInstance(
repo=test_repo, committer="humbedooh", config_data=test.yaml, branch=asfyaml.dataobjects.DEFAULT_BRANCH
)
a.environments_enabled.add("noop")
a.no_cache = True
a.run_parts()