Skip to content

Commit

Permalink
fix: github events api error can only fail for push events
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher committed Dec 9, 2023
1 parent b547814 commit d6fa195
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 41 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ jobs:
uses: ./
with:
changelog_path: ./tests/data/set${{ matrix.set }}/CHANGELOG.md
fail_on_events_api_error: # PRs will fail if this is true
${{ github.event_name == 'pull_request' && 'false' || 'true' }}
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Print action outputs
Expand Down Expand Up @@ -147,7 +145,6 @@ jobs:
id: setup-release
uses: ./
with:
fail_on_events_api_error: true
github_token: ${{ secrets.GH_BOT_TOKEN }}

- name: Create Release
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ The action does the following:
## Inputs
| Name | Description | Default | Required |
|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|----------|
| changelog_path | The path to the changelog file | `CHANGELOG.md` | `false` |
| changelog_path | Path to the changelog file, relative to the GitHub workspace. | `CHANGELOG.md` | `false` |
| dotnet | Whether to create a dotnet version (4 components, e.g. yyyy.mmdd.hhmm.ss). | `false` | `false` |
| event_api_max_attempts | Maximum number of attempts for the GitHub Events API. | `5` | `false` |
| fail_on_events_api_error | Fail if the action cannot find this commit in the events API | `true` | `false` |
| github_token | The GitHub token to use for API calls | | `true` |
| fail_on_events_api_error | Whether to fail if the GitHub Events API returns an error. Will only fail for push events. | `true` | `false` |
| github_token | GitHub token to use for API requests. | | `true` |
| include_tag_prefix_in_output | Whether to include the tag prefix in the output. | `true` | `false` |
| tag_prefix | The tag prefix. This will be used when searching for existing releases in GitHub API. This should not be included in the version within the changelog. | `v` | `false` |

Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ inputs:
default: '5'
required: false
fail_on_events_api_error:
description: "Whether to fail if the GitHub Events API returns an error."
description: "Whether to fail if the GitHub Events API returns an error. Will only fail for push events."
default: 'true'
required: false
github_token:
Expand Down
53 changes: 31 additions & 22 deletions action/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,36 +163,45 @@ def get_push_event_details() -> dict:
}

github_event = get_github_event()

is_pull_request = True if github_event.get("pull_request") else False

try:
# set sha to the head sha of the pull request
github_sha = github_event["pull_request"]["head"]["sha"]
except KeyError:
# not a pull request event
github_sha = os.environ["GITHUB_SHA"]
push_event_details['publish_release'] = True
push_event_details['release_commit'] = github_sha

attempt = 0
push_event = None
while push_event is None and attempt < int(os.getenv('INPUT_EVENT_API_MAX_ATTEMPTS', 5)):
time.sleep(10)
response = requests.get(github_api_url, headers=GITHUB_HEADERS, params=params)

for event in response.json():
if event["type"] == "PushEvent" and event["payload"]["head"] == github_sha:
push_event = event
if event["type"] == "PushEvent" and event["payload"]["ref"] == f"refs/heads/{get_repo_default_branch()}":
break

attempt += 1

if push_event is None:
msg = f":exclamation: ERROR: Push event not found in the GitHub API after {attempt} attempts."
append_github_step_summary(message=msg)
if os.getenv('INPUT_FAIL_ON_EVENTS_API_ERROR', 'false').lower() == 'true':
raise SystemExit(msg)
else:
return push_event_details
if not is_pull_request: # this is a push event
attempt = 0
push_event = None
while push_event is None and attempt < int(os.getenv('INPUT_EVENT_API_MAX_ATTEMPTS', 5)):
time.sleep(10)
response = requests.get(github_api_url, headers=GITHUB_HEADERS, params=params)

for event in response.json():
if event["type"] == "PushEvent" and event["payload"]["head"] == github_sha:
push_event = event
if event["type"] == "PushEvent" and \
event["payload"]["ref"] == f"refs/heads/{get_repo_default_branch()}":
break

attempt += 1

if push_event is None:
msg = f":exclamation: ERROR: Push event not found in the GitHub API after {attempt} attempts."
append_github_step_summary(message=msg)
if os.getenv('INPUT_FAIL_ON_EVENTS_API_ERROR', 'false').lower() == 'true':
raise SystemExit(msg)
else:
return push_event_details
else: # this is a pull request
return push_event_details

# not a pull request
push_event_details['publish_release'] = True

# use regex and convert created at to yyyy.m.d-hhmmss
# created_at: "2023-1-25T10:43:35Z"
Expand Down
60 changes: 48 additions & 12 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
os.environ['GITHUB_WORKSPACE'] = os.path.join(os.getcwd(), 'github', 'workspace')
os.environ['INPUT_CHANGELOG_PATH'] = 'CHANGELOG.md'
os.environ['INPUT_EVENT_API_MAX_ATTEMPTS'] = '1'
os.environ['INPUT_FAIL_ON_EVENTS_API_ERROR'] = 'false'

try:
GITHUB_TOKEN = os.environ['INPUT_GITHUB_TOKEN']
Expand All @@ -24,6 +25,9 @@

GITHUB_HEADERS = {'Authorization': f'token {GITHUB_TOKEN}'}

# globals
COMMIT = None


def pytest_runtest_setup(item):
if 'github_token' in item.fixturenames and not GITHUB_TOKEN:
Expand Down Expand Up @@ -116,19 +120,33 @@ def changelog_set(request):
shutil.rmtree(workspace_dir)


@pytest.fixture(scope='session')
@pytest.fixture(scope='function')
def latest_commit(github_token):
# get commits on the default branch
github_api_url = f"https://api.github.com/repos/{os.environ['GITHUB_REPOSITORY']}/commits"
response = requests.get(
url=github_api_url,
headers=GITHUB_HEADERS,
params={'sha': 'master'},
)
data = response.json()
commit = data[0]['sha']
os.environ['GITHUB_SHA'] = commit
return commit
global COMMIT

if not COMMIT:
# get commits on the default branch
github_api_url = f"https://api.github.com/repos/{os.environ['GITHUB_REPOSITORY']}/commits"
response = requests.get(
url=github_api_url,
headers=GITHUB_HEADERS,
params={'sha': 'master'},
)
data = response.json()
COMMIT = data[0]['sha']

os.environ['GITHUB_SHA'] = COMMIT
yield COMMIT

del os.environ['GITHUB_SHA']


@pytest.fixture(scope='function')
def dummy_commit():
os.environ['GITHUB_SHA'] = 'not-a-real-commit'
yield

del os.environ['GITHUB_SHA']


@pytest.fixture(scope='function', params=[True, False])
Expand All @@ -148,6 +166,24 @@ def github_event_path(request):
os.environ['GITHUB_EVENT_PATH'] = original_value


@pytest.fixture(scope='function')
def dummy_github_event_path():
original_value = os.environ['GITHUB_EVENT_PATH']
os.environ['GITHUB_EVENT_PATH'] = os.path.join(
os.path.dirname(os.path.dirname(__file__)),
'dummy_github_event.json'
)
yield
os.environ['GITHUB_EVENT_PATH'] = original_value


@pytest.fixture(scope='function')
def fail_on_events_api_error():
os.environ['INPUT_FAIL_ON_EVENTS_API_ERROR'] = 'true'
yield
os.environ['INPUT_FAIL_ON_EVENTS_API_ERROR'] = 'false'


@pytest.fixture(params=[True, False], scope='function')
def input_dotnet(request):
os.environ['INPUT_DOTNET'] = str(request.param).lower()
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ def test_get_push_event_details(github_event_path, input_dotnet, latest_commit):
assert main.get_push_event_details()


def test_get_push_event_details_no_event(dummy_github_event_path, dummy_commit):
result = main.get_push_event_details()
assert result['publish_release'] is False
assert result['release_version'] == ''


def test_get_push_event_details_fail_on_error(dummy_github_event_path, dummy_commit, fail_on_events_api_error):
with pytest.raises(SystemExit):
main.get_push_event_details()


def test_parse_changelog(changelog_set):
if changelog_set['changelog_expected']:
changelog_data = main.parse_changelog(changelog_path=changelog_set['changelog_path'])
Expand Down

0 comments on commit d6fa195

Please sign in to comment.