Skip to content
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
174 changes: 174 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: Release

on:
workflow_dispatch:

jobs:
get-plugins:
runs-on: ubuntu-latest
outputs:
plugins: ${{ steps.set-matrix.outputs.plugins_json }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Get changed plugins
id: set-matrix
env:
DIFF_BASE: ${{ github.base_ref }}
run: |
plugins=$(jq -c '[.plugins[].name]' plugins.json)
echo "Changed plugins: $plugins"
echo "plugins_json=$plugins" >> $GITHUB_OUTPUT

create-plugin-release:
needs: get-plugins
runs-on: ubuntu-latest
outputs:
plugin_name: ${{ matrix.plugin }}
upload_url: ${{ steps.create_release.outputs.upload_url }}
permissions:
contents: write
pull-requests: write
strategy:
matrix:
plugin: ${{ fromJSON(needs.get-plugins.outputs.plugins) }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Fetch last tag
run: |
git fetch --tags

LATEST_TAG=$(git describe --abbrev=0 --tags --match "${{ matrix.plugin }}/*" 2>/dev/null || true)
if [ -z "$LATEST_TAG" ]; then
LATEST_TAG=$(git rev-list --max-parents=0 HEAD)
LATEST_VERSION="0.0.0"
echo "Latest tag not found. The first commit of the repository will be used to search for plugin changelogs: $LATEST_TAG"

echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_ENV
exit 0
fi
echo $LATEST_TAG

LATEST_VERSION=$(echo "$LATEST_TAG" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
if [ -n "$LATEST_VERSION" ]; then
LATEST_VERSION="${LATEST_VERSION}"
else
echo "Failed to extract version from tag: $LATEST_TAG" >&2; exit 1;
fi

echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_ENV
- name: Calculate new version
id: new-version
if: env.LATEST_TAG != ''
run: |
LATEST_TAG="${{ env.LATEST_TAG }}"
LATEST_VERSION="${{ env.LATEST_VERSION }}"

set +e
ALL_MESSAGES=$(git log "$LATEST_TAG"..HEAD --format=%B -- ${{ matrix.plugin }} | grep -E "\[(patch|minor|major)\] (feat|fix|refactor): .*")
set -e

if [ -z "$ALL_MESSAGES" ]; then
echo "ALL_MESSAGES is empty. The plugin has not had any changes." >&2;
exit 0
fi

echo "ALL_MESSAGES=$ALL_MESSAGES"

chmod +x ./scripts/helpers/incr_semver.bash

new_patch=""
if [[ "$ALL_MESSAGES" == *"[major]"* ]]; then
new_patch=$(./scripts/helpers/incr_semver.bash "$LATEST_VERSION" major)
echo "NEW_BUMP_TYPE=major" >> $GITHUB_ENV
elif [[ "$ALL_MESSAGES" == *"[minor]"* ]]; then
new_patch=$(./scripts/helpers/incr_semver.bash "$LATEST_VERSION" minor)
echo "NEW_BUMP_TYPE=minor" >> $GITHUB_ENV
else
new_patch=$(./scripts/helpers/incr_semver.bash "$LATEST_VERSION" patch)
echo "NEW_BUMP_TYPE=patch" >> $GITHUB_ENV
fi

echo "NEW_VERSION=$new_patch" >> $GITHUB_ENV

echo "CHANGELOG<<EOF" >> $GITHUB_ENV
echo "$ALL_MESSAGES" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

- name: Create Release
if: env.NEW_VERSION != ''
id: create_release
uses: actions/create-release@v1.1.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ matrix.plugin }}/${{ env.NEW_VERSION }}
release_name: ${{ matrix.plugin }}/${{ env.NEW_VERSION }}
body: ${{ env.CHANGELOG }}
draft: true
prerelease: false
- name: Write upload_url
env:
plugin_upload_url: ${{ steps.create_release.outputs.upload_url }}
run: echo $plugin_upload_url > plugin_upload_url
- name: Produce Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.plugin }}
path: plugin_upload_url

archive-plugin:
needs:
- get-plugins
- create-plugin-release
runs-on: ${{ matrix.os }}
permissions:
contents: write
pull-requests: write
strategy:
matrix:
os: [macos-26, ubuntu-latest]
plugin: ${{ fromJSON(needs.get-plugins.outputs.plugins) }}
steps:
- name: Retrieve Upload Url
uses: actions/download-artifact@v4
with:
name: ${{ matrix.plugin }}
- name: Get plugin_upload_url
run: |
echo $(cat plugin_upload_url)
echo "PLUGIN_UPLOAD_URL=$(cat plugin_upload_url)" >> $GITHUB_ENV
- uses: actions/checkout@v6
if: env.PLUGIN_UPLOAD_URL != ''
- uses: jdx/mise-action@v2
if: env.PLUGIN_UPLOAD_URL != ''
- name: Archive plugin ${{ matrix.plugin }}
if: env.PLUGIN_UPLOAD_URL != ''
run: |
PLUGIN_NAME=${{ matrix.plugin }}
geko plugin archive --path $PLUGIN_NAME
if [[ ${{ matrix.os }} == "ubuntu-latest" ]]; then
ARCH="x86_64"
find "$PLUGIN_NAME" -type f -iname "$PLUGIN_NAME.linux.$ARCH.geko-plugin.zip" -exec cp -v {} "$ARCH.linux-plugin.zip" \;
echo "ARCHIVE_PATH=$ARCH.linux-plugin.zip" >> $GITHUB_ENV
echo "ASSET_NAME=$PLUGIN_NAME.linux.$ARCH.geko-plugin.zip" >> $GITHUB_ENV
else
echo "ARCHIVE_PATH=$PLUGIN_NAME/$PLUGIN_NAME.macos.geko-plugin.zip" >> $GITHUB_ENV
echo "ASSET_NAME=$PLUGIN_NAME.macos.geko-plugin.zip" >> $GITHUB_ENV
fi
- name: Upload release binary
if: env.PLUGIN_UPLOAD_URL != ''
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ env.PLUGIN_UPLOAD_URL }}
asset_path: ${{ env.ARCHIVE_PATH }}
asset_name: ${{ env.ASSET_NAME }}
asset_content_type: application/json
45 changes: 45 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Test

on:
pull_request:
branches:
- main

permissions:
contents: read

jobs:
get-changed-plugins:
runs-on: ubuntu-latest
outputs:
plugins: ${{ steps.set-matrix.outputs.plugins_json }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Get changed plugins
id: set-matrix
env:
DIFF_BASE: ${{ github.base_ref }}
run: |
git fetch origin $DIFF_BASE
chmod +x ./scripts/helpers/changed_plugins.bash
changed=$(./scripts/helpers/changed_plugins.bash)
echo "Changed plugins: $changed"
echo "plugins_json=$changed" >> $GITHUB_OUTPUT

test-plugins:
needs: get-changed-plugins
runs-on: ${{ matrix.os }}
strategy:
matrix:
plugin: ${{ fromJSON(needs.get-changed-plugins.outputs.plugins) }}
os: [macos-26, ubuntu-latest]
steps:
- uses: actions/checkout@v6
- uses: jdx/mise-action@v2
- name: Run tests for plugin
run: |
echo "Testing plugin ${{ matrix.plugin }}"
geko plugin test --path ${{ matrix.plugin }}
8 changes: 7 additions & 1 deletion ExecutablePluginExample/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,11 @@ let package = Package(
name: "ExampleTarget",
dependencies: []
),
.testTarget(
name: "ExecutablePluginExampleTests",
dependencies: [
"ExampleTarget"
]
)
]
)
)
2 changes: 1 addition & 1 deletion ExecutablePluginExample/Plugin.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ProjectDescription

let plugin = Plugin(
name: "GekoPlugin",
name: "ExecutablePluginExample",
executables: [
ExecutablePlugin(name: "ExampleGekoExecutable")
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import ExampleTarget

final class ExampleTargetTests: XCTestCase {
func test_example() async throws {
XCTAssert(true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ let package = Package(
.product(name: "ProjectDescription", package: "project-description"),
],
path: "ProjectDescriptionHelpers"
),
.testTarget(
name: "WorkspaceMapperExampleTests",
dependencies: [
"WorkspaceMapperExample"
]
)
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation
import XCTest
@testable import WorkspaceMapperExample

final class WorkspaceMapperExampleTests: XCTestCase {
func test_example() async throws {
XCTAssert(true)
}
}
2 changes: 2 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[tools]
"github:geko-tech/geko" = { version = "1.0.0", version_prefix = "Geko@" }
7 changes: 7 additions & 0 deletions plugins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"plugins": [
{ "name": "ExecutablePluginExample" },
{ "name": "WorkspaceMapperExample" },
{ "name": "ImpactAnalysis"}
]
}
22 changes: 22 additions & 0 deletions scripts/helpers/changed_plugins.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail

PLUGINS_FILE="plugins.json"

changed_files=$(git --no-pager diff --name-only --merge-base FETCH_HEAD)

if [[ -z "$changed_files" ]]; then
exit 0
fi

plugins=$(jq -r '.plugins[].name' "$PLUGINS_FILE")

changed_plugins=()

for plugin in $plugins; do
if echo "$changed_files" | grep -q "^${plugin}/"; then
changed_plugins+=("$plugin")
fi
done

jq -nc '$ARGS.positional' --args "${changed_plugins[@]}"
31 changes: 31 additions & 0 deletions scripts/helpers/incr_semver.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

# Function to increment a semantic version string
# Usage: incr_semver <version_string> [major|minor|patch]
IFS=.
parts=($1)
level=$2

# Default to patch if no level specified
[[ -z "$level" ]] && level="patch"

case "$level" in
major)
((parts[0]++))
parts[1]=0
parts[2]=0
;;
minor)
((parts[1]++))
parts[2]=0
;;
patch)
((parts[2]++))
;;
*)
echo "Invalid level specified: $level. Use major, minor, or patch." >&2
return 1
;;
esac

echo "${parts[0]}.${parts[1]}.${parts[2]}"