Skip to content

Add CI pipeline for creating self-hosted runners #5

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

Merged
merged 5 commits into from
Dec 22, 2022

Conversation

dennisameling
Copy link
Contributor

@dennisameling dennisameling commented Dec 20, 2022

This is a CI pipeline to create one or multiple Azure arm64 VMs with GfW and the GitHub Actions runner preinstalled and provisioned. The VMs are deallocated immediately after creation so they are prepared for later use.

Here's an example run: https://github.com/dennisameling/azure-arm64-gh-actions-runner/actions/runs/3740740959/jobs/6349467898

The runner is then added to the repo correctly 🎉 it's offline because we deallocate the VM immediately after setup in the CI pipeline.

image

After running a job on the runner, it's automatically removed thanks to the --ephemeral flag:

image

ACTIONS_RUNNER_ORG: "${{ github.event.inputs.runner_org }}"
ACTIONS_RUNNER_REPO: "${{ github.event.inputs.runner_repo }}"
# This has to be a public URL that the VM can access after creation
POST_DEPLOYMENT_SCRIPT_URL: https://raw.githubusercontent.com/git-for-windows/git-for-windows-automation/main/azure-self-hosted-runners/post-deployment-script.ps1
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This URL will only work after this PR has been merged.

Copy link
Member

Choose a reason for hiding this comment

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

Obviously. We could use ${{ github.repository }} and ${{ github.ref_name }} to make it less specific, though.

Comment on lines +145 to +156
{
"name": "[variables('vnetName')]",
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2020-11-01",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": "[parameters('addressPrefixes')]"
},
"subnets": "[parameters('subnets')]"
}
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This currently creates one virtual network per VM which might be overkill. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Once we're comfortable with not requiring RDP access (and hence a public IP), it will make sense to switch to a single virtual network that is hosted in a separate resource group, I think. For now, let's keep your current solution.

# az ad sp create-for-rbac --name "{YOUR_DESCRIPTIVE_NAME_HERE}" --role contributor \
# --scopes /subscriptions/{SUBSCRIPTION_ID_HERE}/resourceGroups/{RESOURCE_GROUP_HERE} \
# --sdk-auth
# AZURE_RESOURCE_GROUP - Resource group to create the runner(s) in
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I assumed that you want to create these VMs in their own, dedicated resource group. This pipeline expects the resource group to be created in Azure prior to running the pipeline.

Copy link
Member

Choose a reason for hiding this comment

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

That makes sense. Then we can delete the resource group which should delete everything contained therein.

Comment on lines +157 to +171
{
"name": "[parameters('publicIpAddressName1')]",
"type": "Microsoft.Network/publicIpAddresses",
"apiVersion": "2020-08-01",
"location": "[parameters('location')]",
"properties": {
"publicIpAllocationMethod": "[parameters('publicIpAddressType')]"
},
"sku": {
"name": "[parameters('publicIpAddressSku')]"
},
"zones": [
"1"
]
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The VMs currently have public IPs for RDPing into them, which might be useful for initial testing. You can always remove this part and not assign a public IP, but then you'll need another solution to be able to RDP into the VMs if needed.

Copy link
Member

Choose a reason for hiding this comment

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

I planned on using https://github.com/mxschmitt/action-tmate for debugging, if it ever was needed. Maybe make it an input parameter whether or not RDP is enabled? That way we could quickly change it in GitForWindowsHelper.

Write-Output "Installing GitHub Actions runner ${GitHubActionsRunnerVersion} as a Windows service with labels ${GithubActionsRunnerLabels}..."

Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("${GitHubActionsRunnerPath}\actions-runner-win-${GithubActionsRunnerArch}-${GitHubActionsRunnerVersion}.zip", $GitHubActionsRunnerPath)
cmd.exe /c "${GitHubActionsRunnerPath}\config.cmd" --unattended --ephemeral --name ${GithubActionsRunnerName} --runasservice --labels ${GithubActionsRunnerLabels} --url ${GithubActionsRunnerRegistrationUrl} --token ${GitHubActionsRunnerToken}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added --ephemeral so that the VM will only run a single GitHub Actions job. We'll need to add some logic to shutdown and remove the VM after use. I'm thinking about something like:

  • Setting the brand-new ACTIONS_RUNNER_HOOK_JOB_COMPLETED env variable on the VM that runs a script after the job has finished. This script could:
  • From that script, call the Azure Instance Metadata Service on 169.254.169.254 to figure out the name of the currently running VM. Something like this should work:
$Proxy=New-object System.Net.WebProxy
$WebSession=new-object Microsoft.PowerShell.Commands.WebRequestSession
$WebSession.Proxy=$Proxy
$Data=Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" -WebSession $WebSession | ConvertTo-Json -Depth 64
$ParsedData = $Data| ConvertFrom-Json
echo $ParsedData.compute.name
# Returns e.g. actions-runner-20221220130445797318063
echo $ParsedData.compute.resourceGroupName
# Returns e.g. github-actions-runners
echo $ParsedData.compute.resourceId
# Returns e.g. /subscriptions/YOUR_SUB_ID_HERE/resourceGroups/github-actions-runners/providers/Microsoft.Compute/virtualMachines/actions-runner-20221220130445797318063
  • The script should then trigger some sort of webhook call to request removal of the VM by the GfW bot, given the name and resource group name (or resourceId) we just got from the metadata endpoint. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good!

FWIW I thought that the GitForWindowsHelper GitHub App would receive a webhook event after the workflow run completed that would contain enough information so that we could remove the entire resource group (which I hoped would automatically stop and delete the VM). Here is an example for a recent delivery of such a check_run.completed webhook event:

Headers
Request method: POST
Accept: */*
content-type: application/json
User-Agent: GitHub-Hookshot/2179efe
X-GitHub-Delivery: 290d2ca0-8141-11ed-98cb-b0a992770f94
X-GitHub-Event: check_run
X-GitHub-Hook-ID: 392499201
X-GitHub-Hook-Installation-Target-ID: 246505
X-GitHub-Hook-Installation-Target-Type: integration
X-Hub-Signature: sha1=85a088f44616d331bf60f6c119727d5e81b95aa6
X-Hub-Signature-256: sha256=71e60249b346e085b93df13a43a79237ac3db4166d7486eaeea83b913af59151
Payload
{
  "action": "completed",
  "check_run": {
    "id": 10233939147,
    "name": "win+VS build (arm64)",
    "node_id": "CR_kwDOAWJAkM8AAAACYf2Eyw",
    "head_sha": "6a20512f99c2a5012d0972d1f926a835730c274d",
    "external_id": "e1b98089-497b-54b4-42e0-e2656d08cc2a",
    "url": "https://api.github.com/repos/git-for-windows/git/check-runs/10233939147",
    "html_url": "https://github.com/git-for-windows/git/actions/runs/3750386564/jobs/6370043175",
    "details_url": "https://github.com/git-for-windows/git/actions/runs/3750386564/jobs/6370043175",
    "status": "completed",
    "conclusion": "success",
    "started_at": "2022-12-21T15:01:09Z",
    "completed_at": "2022-12-21T15:07:16Z",
    "output": {
      "title": null,
      "summary": null,
      "text": null,
      "annotations_count": 0,
      "annotations_url": "https://api.github.com/repos/git-for-windows/git/check-runs/10233939147/annotations"
    },
    "check_suite": {
      "id": 9993156801,
      "node_id": "CS_kwDOAWJAkM8AAAACU6N4wQ",
      "head_branch": "shears/main",
      "head_sha": "6a20512f99c2a5012d0972d1f926a835730c274d",
      "status": "queued",
      "conclusion": null,
      "url": "https://api.github.com/repos/git-for-windows/git/check-suites/9993156801",
      "before": "3dd6ea96c600566c590fb3eedfde352fca5b7067",
      "after": "6a20512f99c2a5012d0972d1f926a835730c274d",
      "pull_requests": [

      ],
      "app": {
        "id": 15368,
        "slug": "github-actions",
        "node_id": "MDM6QXBwMTUzNjg=",
        "owner": {
          "login": "github",
          "id": 9919,
          "node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
          "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
          "gravatar_id": "",
          "url": "https://api.github.com/users/github",
          "html_url": "https://github.com/github",
          "followers_url": "https://api.github.com/users/github/followers",
          "following_url": "https://api.github.com/users/github/following{/other_user}",
          "gists_url": "https://api.github.com/users/github/gists{/gist_id}",
          "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/github/subscriptions",
          "organizations_url": "https://api.github.com/users/github/orgs",
          "repos_url": "https://api.github.com/users/github/repos",
          "events_url": "https://api.github.com/users/github/events{/privacy}",
          "received_events_url": "https://api.github.com/users/github/received_events",
          "type": "Organization",
          "site_admin": false
        },
        "name": "GitHub Actions",
        "description": "Automate your workflow from idea to production",
        "external_url": "https://help.github.com/en/actions",
        "html_url": "https://github.com/apps/github-actions",
        "created_at": "2018-07-30T09:30:17Z",
        "updated_at": "2019-12-10T19:04:12Z",
        "permissions": {
          "actions": "write",
          "administration": "read",
          "checks": "write",
          "contents": "write",
          "deployments": "write",
          "discussions": "write",
          "issues": "write",
          "merge_queues": "write",
          "metadata": "read",
          "packages": "write",
          "pages": "write",
          "pull_requests": "write",
          "repository_hooks": "write",
          "repository_projects": "write",
          "security_events": "write",
          "statuses": "write",
          "vulnerability_alerts": "read"
        },
        "events": [
          "branch_protection_rule",
          "check_run",
          "check_suite",
          "create",
          "delete",
          "deployment",
          "deployment_status",
          "discussion",
          "discussion_comment",
          "fork",
          "gollum",
          "issues",
          "issue_comment",
          "label",
          "merge_group",
          "milestone",
          "page_build",
          "project",
          "project_card",
          "project_column",
          "public",
          "pull_request",
          "pull_request_review",
          "pull_request_review_comment",
          "push",
          "registry_package",
          "release",
          "repository",
          "repository_dispatch",
          "status",
          "watch",
          "workflow_dispatch",
          "workflow_run"
        ]
      },
      "created_at": "2022-12-21T15:00:34Z",
      "updated_at": "2022-12-21T15:07:17Z"
    },
    "app": {
      "id": 15368,
      "slug": "github-actions",
      "node_id": "MDM6QXBwMTUzNjg=",
      "owner": {
        "login": "github",
        "id": 9919,
        "node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
        "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
        "gravatar_id": "",
        "url": "https://api.github.com/users/github",
        "html_url": "https://github.com/github",
        "followers_url": "https://api.github.com/users/github/followers",
        "following_url": "https://api.github.com/users/github/following{/other_user}",
        "gists_url": "https://api.github.com/users/github/gists{/gist_id}",
        "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
        "subscriptions_url": "https://api.github.com/users/github/subscriptions",
        "organizations_url": "https://api.github.com/users/github/orgs",
        "repos_url": "https://api.github.com/users/github/repos",
        "events_url": "https://api.github.com/users/github/events{/privacy}",
        "received_events_url": "https://api.github.com/users/github/received_events",
        "type": "Organization",
        "site_admin": false
      },
      "name": "GitHub Actions",
      "description": "Automate your workflow from idea to production",
      "external_url": "https://help.github.com/en/actions",
      "html_url": "https://github.com/apps/github-actions",
      "created_at": "2018-07-30T09:30:17Z",
      "updated_at": "2019-12-10T19:04:12Z",
      "permissions": {
        "actions": "write",
        "administration": "read",
        "checks": "write",
        "contents": "write",
        "deployments": "write",
        "discussions": "write",
        "issues": "write",
        "merge_queues": "write",
        "metadata": "read",
        "packages": "write",
        "pages": "write",
        "pull_requests": "write",
        "repository_hooks": "write",
        "repository_projects": "write",
        "security_events": "write",
        "statuses": "write",
        "vulnerability_alerts": "read"
      },
      "events": [
        "branch_protection_rule",
        "check_run",
        "check_suite",
        "create",
        "delete",
        "deployment",
        "deployment_status",
        "discussion",
        "discussion_comment",
        "fork",
        "gollum",
        "issues",
        "issue_comment",
        "label",
        "merge_group",
        "milestone",
        "page_build",
        "project",
        "project_card",
        "project_column",
        "public",
        "pull_request",
        "pull_request_review",
        "pull_request_review_comment",
        "push",
        "registry_package",
        "release",
        "repository",
        "repository_dispatch",
        "status",
        "watch",
        "workflow_dispatch",
        "workflow_run"
      ]
    },
    "pull_requests": [

    ]
  },
  "repository": {
    "id": 23216272,
    "node_id": "MDEwOlJlcG9zaXRvcnkyMzIxNjI3Mg==",
    "name": "git",
    "full_name": "git-for-windows/git",
    "private": false,
    "owner": {
      "login": "git-for-windows",
      "id": 4571183,
      "node_id": "MDEyOk9yZ2FuaXphdGlvbjQ1NzExODM=",
      "avatar_url": "https://avatars.githubusercontent.com/u/4571183?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/git-for-windows",
      "html_url": "https://github.com/git-for-windows",
      "followers_url": "https://api.github.com/users/git-for-windows/followers",
      "following_url": "https://api.github.com/users/git-for-windows/following{/other_user}",
      "gists_url": "https://api.github.com/users/git-for-windows/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/git-for-windows/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/git-for-windows/subscriptions",
      "organizations_url": "https://api.github.com/users/git-for-windows/orgs",
      "repos_url": "https://api.github.com/users/git-for-windows/repos",
      "events_url": "https://api.github.com/users/git-for-windows/events{/privacy}",
      "received_events_url": "https://api.github.com/users/git-for-windows/received_events",
      "type": "Organization",
      "site_admin": false
    },
    "html_url": "https://github.com/git-for-windows/git",
    "description": "A fork of Git containing Windows-specific patches.",
    "fork": true,
    "url": "https://api.github.com/repos/git-for-windows/git",
    "forks_url": "https://api.github.com/repos/git-for-windows/git/forks",
    "keys_url": "https://api.github.com/repos/git-for-windows/git/keys{/key_id}",
    "collaborators_url": "https://api.github.com/repos/git-for-windows/git/collaborators{/collaborator}",
    "teams_url": "https://api.github.com/repos/git-for-windows/git/teams",
    "hooks_url": "https://api.github.com/repos/git-for-windows/git/hooks",
    "issue_events_url": "https://api.github.com/repos/git-for-windows/git/issues/events{/number}",
    "events_url": "https://api.github.com/repos/git-for-windows/git/events",
    "assignees_url": "https://api.github.com/repos/git-for-windows/git/assignees{/user}",
    "branches_url": "https://api.github.com/repos/git-for-windows/git/branches{/branch}",
    "tags_url": "https://api.github.com/repos/git-for-windows/git/tags",
    "blobs_url": "https://api.github.com/repos/git-for-windows/git/git/blobs{/sha}",
    "git_tags_url": "https://api.github.com/repos/git-for-windows/git/git/tags{/sha}",
    "git_refs_url": "https://api.github.com/repos/git-for-windows/git/git/refs{/sha}",
    "trees_url": "https://api.github.com/repos/git-for-windows/git/git/trees{/sha}",
    "statuses_url": "https://api.github.com/repos/git-for-windows/git/statuses/{sha}",
    "languages_url": "https://api.github.com/repos/git-for-windows/git/languages",
    "stargazers_url": "https://api.github.com/repos/git-for-windows/git/stargazers",
    "contributors_url": "https://api.github.com/repos/git-for-windows/git/contributors",
    "subscribers_url": "https://api.github.com/repos/git-for-windows/git/subscribers",
    "subscription_url": "https://api.github.com/repos/git-for-windows/git/subscription",
    "commits_url": "https://api.github.com/repos/git-for-windows/git/commits{/sha}",
    "git_commits_url": "https://api.github.com/repos/git-for-windows/git/git/commits{/sha}",
    "comments_url": "https://api.github.com/repos/git-for-windows/git/comments{/number}",
    "issue_comment_url": "https://api.github.com/repos/git-for-windows/git/issues/comments{/number}",
    "contents_url": "https://api.github.com/repos/git-for-windows/git/contents/{+path}",
    "compare_url": "https://api.github.com/repos/git-for-windows/git/compare/{base}...{head}",
    "merges_url": "https://api.github.com/repos/git-for-windows/git/merges",
    "archive_url": "https://api.github.com/repos/git-for-windows/git/{archive_format}{/ref}",
    "downloads_url": "https://api.github.com/repos/git-for-windows/git/downloads",
    "issues_url": "https://api.github.com/repos/git-for-windows/git/issues{/number}",
    "pulls_url": "https://api.github.com/repos/git-for-windows/git/pulls{/number}",
    "milestones_url": "https://api.github.com/repos/git-for-windows/git/milestones{/number}",
    "notifications_url": "https://api.github.com/repos/git-for-windows/git/notifications{?since,all,participating}",
    "labels_url": "https://api.github.com/repos/git-for-windows/git/labels{/name}",
    "releases_url": "https://api.github.com/repos/git-for-windows/git/releases{/id}",
    "deployments_url": "https://api.github.com/repos/git-for-windows/git/deployments",
    "created_at": "2014-08-22T07:07:36Z",
    "updated_at": "2022-12-21T08:24:32Z",
    "pushed_at": "2022-12-21T15:00:55Z",
    "git_url": "git://github.com/git-for-windows/git.git",
    "ssh_url": "[email protected]:git-for-windows/git.git",
    "clone_url": "https://github.com/git-for-windows/git.git",
    "svn_url": "https://github.com/git-for-windows/git",
    "homepage": "http://git-scm.com/",
    "size": 267177,
    "stargazers_count": 7204,
    "watchers_count": 7204,
    "language": "C",
    "has_issues": true,
    "has_projects": true,
    "has_downloads": true,
    "has_wiki": true,
    "has_pages": false,
    "has_discussions": true,
    "forks_count": 2306,
    "mirror_url": null,
    "archived": false,
    "disabled": false,
    "open_issues_count": 151,
    "license": {
      "key": "other",
      "name": "Other",
      "spdx_id": "NOASSERTION",
      "url": null,
      "node_id": "MDc6TGljZW5zZTA="
    },
    "allow_forking": true,
    "is_template": false,
    "web_commit_signoff_required": false,
    "topics": [
      "hacktoberfest"
    ],
    "visibility": "public",
    "forks": 2306,
    "open_issues": 151,
    "watchers": 7204,
    "default_branch": "main"
  },
  "organization": {
    "login": "git-for-windows",
    "id": 4571183,
    "node_id": "MDEyOk9yZ2FuaXphdGlvbjQ1NzExODM=",
    "url": "https://api.github.com/orgs/git-for-windows",
    "repos_url": "https://api.github.com/orgs/git-for-windows/repos",
    "events_url": "https://api.github.com/orgs/git-for-windows/events",
    "hooks_url": "https://api.github.com/orgs/git-for-windows/hooks",
    "issues_url": "https://api.github.com/orgs/git-for-windows/issues",
    "members_url": "https://api.github.com/orgs/git-for-windows/members{/member}",
    "public_members_url": "https://api.github.com/orgs/git-for-windows/public_members{/member}",
    "avatar_url": "https://avatars.githubusercontent.com/u/4571183?v=4",
    "description": ""
  },
  "sender": {
    "login": "git-for-windows-ci",
    "id": 24522801,
    "node_id": "MDQ6VXNlcjI0NTIyODAx",
    "avatar_url": "https://avatars.githubusercontent.com/u/24522801?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/git-for-windows-ci",
    "html_url": "https://github.com/git-for-windows-ci",
    "followers_url": "https://api.github.com/users/git-for-windows-ci/followers",
    "following_url": "https://api.github.com/users/git-for-windows-ci/following{/other_user}",
    "gists_url": "https://api.github.com/users/git-for-windows-ci/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/git-for-windows-ci/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/git-for-windows-ci/subscriptions",
    "organizations_url": "https://api.github.com/users/git-for-windows-ci/orgs",
    "repos_url": "https://api.github.com/users/git-for-windows-ci/repos",
    "events_url": "https://api.github.com/users/git-for-windows-ci/events{/privacy}",
    "received_events_url": "https://api.github.com/users/git-for-windows-ci/received_events",
    "type": "User",
    "site_admin": false
  },
  "installation": {
    "id": 31544731,
    "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMzE1NDQ3MzE="
  }
}

I guess there is not quite enough information to tell whether this was run on a self-hosted runner, basically because we only get a check_run which is not a job that would have been run on a particular runner. But I suspect the relevant information might only be a call to e.g. https://docs.github.com/en/rest/actions/workflow-runs#get-a-workflow-run away, maybe also https://docs.github.com/en/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run would be needed.

with:
resourceGroupName: ${{ secrets.AZURE_RESOURCE_GROUP }}
template: ./azure-self-hosted-runners/azure-arm-template.json
parameters: ./azure-self-hosted-runners/azure-arm-template-example-parameters.json githubActionsRunnerRegistrationUrl="${{ env.ACTIONS_RUNNER_REGISTRATION_URL }}" githubActionsRunnerToken="${{ env.ACTIONS_RUNNER_TOKEN }}" postDeploymentPsScriptUrl="${{ env.POST_DEPLOYMENT_SCRIPT_URL }}" virtualMachineName=${{ steps.generate-vm-name.outputs.vm_name }} virtualMachineSize=Standard_D8pls_v5 publicIpAddressName1=${{ steps.generate-vm-name.outputs.vm_name }}-ip adminUsername=${{ secrets.AZURE_VM_USERNAME }} adminPassword=${{ secrets.AZURE_VM_PASSWORD }}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Standard_D8pls_v5 is an 8-core arm64 VM with 16GB of RAM. A machine with less specs might be sufficient too.

Copy link
Member

Choose a reason for hiding this comment

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

Let's leave it for now, I'll monitor the usage. If I'm running out of money too fast, I'll just scale it down.

@dscho
Copy link
Member

dscho commented Dec 21, 2022

Woooooow! Nice work @dennisameling!

Unfortunately, I am a bit too frazzled today to have a closer look, as I have been struggling with the Git for Windows v2.39.0(2) release. But I hope to get to it tomorrow, otherwise in the New Year (I am planning on leaving the computer turned off for quite a bit over the next two weeks).

This will be super awesome!

@dennisameling
Copy link
Contributor Author

dennisameling commented Dec 21, 2022

But I hope to get to it tomorrow, otherwise in the New Year (I am planning on leaving the computer turned off for quite a bit over the next two weeks).

That makes a ton of sense - thanks once again for all your quick and incredibly accurate reviews and feedback. It's a pleasure working on things together this way. I'm very excited that we're finally getting close to a sustainable solution for arm64 support after 2+ years, while (potentially) also paving the way for clang64 support at some point in the future 😄

Shall we focus our efforts on the git-extra stuff for now? Looks like that'll unblock quite some other things. You mentioned that the old references will need to be updated in quite some places. I'm thinking to create a PR with many small, easy-to-review commits to update those across the board. It'd be great if we can get this PR merged soon so that I can test with the actual packages from the GfW Pacman repos. WDYT?

@dscho
Copy link
Member

dscho commented Dec 22, 2022

You mentioned that the old references will need to be updated in quite some places. I'm thinking to create a PR with many small, easy-to-review commits to update those across the board.

Yes, that would be good. I think the best starting point will be git grep -w git-extra in build-extra (ignoring the versions/ hits) and probably also the wiki:

$ git -C /usr/src/build-extra grep -w git-extra -- ':(exclude)versions/'

I grouped and annotated output in the following. First, the parts that need to be changed when we switch from installing git-extra to installing mingw-w64-<arch>-git-extra instead (which will also need that replaces addition to PKGBUILD):

commit-msys2.sh:	sed -ne '/.* M\tvar\/lib\/pacman\/local\/git-extra-[1-9].*\/desc$/d' \
commit-msys2.sh:		':(exclude)var/lib/pacman/local/git-extra-*/desc' \
git-extra/update-via-pacman.bat:@ECHO Wrapping up: re-install git-extra
git-extra/update-via-pacman.bat:@pacman -S --noconfirm git-extra
git-extra/update-via-pacman.bat:@ECHO End of re-install of git-extra
make-file-list.sh:git-extra openssh $UTIL_PACKAGES"
please.sh:		# git-extra rewrites some files owned by other packages,
please.sh:			'pacman -S '$force' --noconfirm git-extra' ||
please.sh:		die "Cannot update git-extra in %s\n" "$sdk"
please.sh:			# Make sure we have the git-extra package locally, as
please.sh:			   'pkg=/var/cache/pacman/pkg/$(pacman -Q git-extra |
please.sh:				pacman -Sw --noconfirm git-extra &&
please.sh:			pacman -S --noconfirm git-extra &&
please.sh:			pacman -S --noconfirm git-extra' ||
please.sh:			'pacman -S --noconfirm git-extra' &&
please.sh:			'pacman -S --noconfirm git-extra'
please.sh:	# if built-ins are still original hard-links, reinstall git-extra
please.sh:		'pacman -S --noconfirm git-extra'
please.sh:		'pacman -S --noconfirm git-extra'
please.sh:		(. /var/lib/pacman/local/git-extra-*/install && post_install)

These parts need to be augmented with the new package name:

get-sources.sh:		git-extra|mingw-w64-x86_64-git|mingw-w64-i686-git|msys2-runtime|mingw-w64-x86_64-git-credential-manager|mingw-w64-i686-git-credential-manager|mingw-w64-x86_64-git-credential-manager-core|mingw-w64-i686-git-credential-manager-core|mingw-w64-i686-git-lfs|mingw-w64-x86_64-git-lfs|curl|mingw-w64-i686-curl|mingw-w64-x86_64-curl|mingw-w64-i686-wintoast|mingw-w64-x86_64-wintoast|bash|heimdal|perl|openssh)
please.sh:	git-extra)

Here are the parts that need to be changed once we rename the git-extra/ directory to mingw-w64-git-extra/ in build-extra:

.github/workflows/build-and-deploy.yml:          if test git-extra != "$PACKAGE_TO_BUILD" && test "z${PACKAGE_TO_BUILD#mingw-w64-}" = "z$PACKAGE_TO_BUILD"
.gitignore:/git-extra/pkg/
.gitignore:/git-extra/src/
.gitignore:/git-extra/git-extra-*.pkg.tar.xz
.gitignore:/git-extra/git-extra-*.src.tar.gz
git-extra/vimrc:" This source file comes from git-for-windows build-extra repository (git-extra/vimrc)
please.sh:# 2) release a new Pacman package, e.g. git-extra or msys2-runtime
please.sh:#	./please.sh build git-extra
please.sh:#	./please.sh install git-extra
please.sh:#	./please.sh upload git-extra

These lines won't need changing, at least not for a long time (until the time when we stop building the superseded git-extra package altogether):

git-extra/PKGBUILD:_realname="git-extra"
git-extra/PKGBUILD:install='git-extra.install'
git-extra/PKGBUILD:# The old package name, git-extra, was causing problems as it's _actually_ a MINGW-package.
git-extra/PKGBUILD:  conflicts=('mingw-w64-clang-aarch64-git-extra' 'mingw-w64-x86_64-git-extra' 'mingw-w64-i686-git-extra')
git-extra/PKGBUILD:package_mingw-w64-x86_64-git-extra() {
git-extra/PKGBUILD:  conflicts=('git-extra' 'mingw-w64-clang-aarch64-git-extra' 'mingw-w64-i686-git-extra')
git-extra/PKGBUILD:  provides=('git-extra')
git-extra/PKGBUILD:package_mingw-w64-i686-git-extra() {
git-extra/PKGBUILD:  conflicts=('git-extra' 'mingw-w64-x86_64-git-extra' 'mingw-w64-clang-aarch64-git-extra')
git-extra/PKGBUILD:  provides=('git-extra')
git-extra/PKGBUILD:package_mingw-w64-clang-aarch64-git-extra() {
git-extra/PKGBUILD:  conflicts=('git-extra' 'mingw-w64-x86_64-git-extra' 'mingw-w64-i686-git-extra')
git-extra/PKGBUILD:  provides=('git-extra')
git-extra/git-extra.install:		# Revert change by prior versions of git-extra.
git-extra/git-extra.install:		# Revert change by prior versions of git-extra.
git-extra/git-extra.install:		sed -i -e '/^# Added by git-extra/{N;/^\(.*\n\)\?Ciphers +[a-z].*cbc/d}' /etc/ssh/ssh_config
git-extra/git-extra.install:			'# Added by git-extra' \
git-extra/git-extra.install:			'# Added by git-extra' \
git-extra/git-extra.install.in:		# Revert change by prior versions of git-extra.
git-extra/git-extra.install.in:		# Revert change by prior versions of git-extra.
git-extra/git-extra.install.in:		sed -i -e '/^# Added by git-extra/{N;/^\(.*\n\)\?Ciphers +[a-z].*cbc/d}' /etc/ssh/ssh_config
git-extra/git-extra.install.in:			'# Added by git-extra' \
git-extra/git-extra.install.in:			'# Added by git-extra' \
git-extra/git-sdk.sh:		printf "%s " git git-extra msys2-runtime installer \
git-extra/git-sdk.sh:		git-extra|git-for-windows-keyring|mingw-w64-cv2pdb|\
git-extra/git-sdk.sh:			pacman -Syyu git-extra &&
git-extra/git-sdk.sh:			sdk $cmd git-extra &&
git-extra/git-sdk.sh:			sdk init git-extra &&
git-extra/proxy-lookup.c: * included in Git for Windows' git-extra package.
pacman-helper.sh:		git-extra-*.pkg.tar.xz) arch=${file%.pkg.tar.xz}; arch=${arch##*-}; key=${arch}_mingw;;
please.sh:	git-extra)
please.sh:			git commit -s -m "git-extra: adjust checksums" PKGBUILD &&
please.sh:		 if test git-extra.install.in -nt git-extra.install
please.sh:			if ! git diff-files --quiet -- git-extra.install
please.sh:					"git-extra: regenerate .install file" \
please.sh:					git-extra.install

There is also this line (please.sh:2063, not to be confused with please.sh:408) that also needs to be addressed when we stop building the superseded git-extra package:

please.sh:		git-extra)
$ git -C git-for-windows.wiki/ grep -w git-extra
Install-inside-MSYS2-proper.md:        pacman -S mingw-w64-x86_64-{git,git-doc-html,git-doc-man} git-extra
Install-inside-MSYS2-proper.md:The `git-extra` package modifies the MSYS2 environment heavily (sometimes in ways that are tedious to undo).  The package can be skipped if you want to keep your MSYS2 pristine.  As of this writing, the package:
Install-or-update-inside-MSYS2,-Cygwin-or-Git-for-windows-itself.md:With the script `getgit` introduced by [git-for-windows/build-extra#261](https://github.com/git-for-windows/build-extra/pull/261), you can download and run the script or just run `curl https://raw.githubusercontent.com/git-for-windows/build-extra/HEAD/git-extra/getgit | bash`.
Making-an-installer.md:Short version: you will need to run `make strip` in `/usr/src/git` before `make install`, and you will also need to run to call `pacman -S git-extra` afterwards.
Making-an-installer.md:## Why `pacman -S git-extra`?
Making-an-installer.md:The `pacman -S git-extra` part is defined elsewhere yet: in `/usr/src/build-extra/please.sh`. Its purpose is to replace many hardlinked copies in `/mingw64/libexec/git-core/git-*.exe` with what Git for Windows calls the "Git wrapper": a small executable that does nothing else but call `git.exe` with the appropriate subcommand name.
Package-management.md:- [build-extra](https://github.com/git-for-windows/build-extra) contains the `git-extra` package information,
Technical-overview.md:In some cases, the change you want to make is not in git itself, but in the additional files needed to emulate the *ix environment git expects (things like `grep`, `find`, `cat`,...), or in additional helper files (e.g. `start-ssh-agent.cmd`). These files come from [Msys](https://github.com/git-for-windows/MSYS2-packages) and [Mingw](https://github.com/git-for-windows/MINGW-packages) packages. Please see the documentation for how to make [changes to these packages](Package-management#technical-details). Some files are also in the `build-extras` repo in the subdir [`git-extra`](https://github.com/git-for-windows/build-extra/tree/HEAD/git-extra) (the script which calls notepad as a commit message editor, diff filter for word files,...). The source code for these files are also under `/usr/src` but need to be checked out first (e.g. `cd /usr/src/MINGW-packages && git fetch && git checkout main`).
Updating-your-SDK.md:1. 	Run `update-via-pacman.bat` in the command window (it will always re-install the `git-extra` package at the end)

I think we will need to change these in conjunction with switching over to installing mingw-w64-<arch>-git-extra instead of git-extra.

…repo

This makes the workflow very useful also to other projects who want to
imitate what Git for Windows does.

Signed-off-by: Johannes Schindelin <[email protected]>
This makes it more convenient to run this workflow manually.

Signed-off-by: Johannes Schindelin <[email protected]>
This not only helps consistency, but also makes it easier to turn the
workflow into a `push`-triggered one, for testing.

Signed-off-by: Johannes Schindelin <[email protected]>
In git-for-windows-automation, we want to act as the GitForWindowsHelper
GitHub App as much as possible.

Signed-off-by: Johannes Schindelin <[email protected]>
@dscho
Copy link
Member

dscho commented Dec 22, 2022

Look at that!

image

Created by https://github.com/git-for-windows/git-for-windows-automation/actions/runs/3760042983... I'll push the changes I made on top of 6cfc1d0 (and that I used to run this workflow) in a moment.

@dscho
Copy link
Member

dscho commented Dec 22, 2022

Created by https://github.com/git-for-windows/git-for-windows-automation/actions/runs/3760042983...

It looks as if the workflow basically sits on its hands for 7.5 minutes, waiting for Azure. I do not see anything in actions/arm-deploy that would allow us to "fire and forget" about this. I guess we can wait for the VM to be created, but it looks like a bit of a waste of build minutes to me.

Together with the fact that deallocating the VM takes another ~1¼ minutes, I wonder whether the strategy is worth the effort to always keep one runner pretty much ready to go at all times. We could simply spin up the runner on demand instead, after all, a ~8 minute queue time is not that terrible for jobs that will run only once in a while. But I guess it's nicer to wait only a minute for the VM to spin up and we're almost there...

@dennisameling what are your thoughts on this matter?

@dennisameling
Copy link
Contributor Author

I guess we can wait for the VM to be created, but it looks like a bit of a waste of build minutes to me.

I agree it's a waste of build minutes, but we could leave it as-is for now and create an issue in https://github.com/Azure/arm-deploy/ for them to add a "fire and forget" feature. WDYT?

We could simply spin up the runner on demand instead, after all, a ~8 minute queue time is not that terrible for jobs that will run only once in a while

We could certainly start with that. Most builds/pipelines take 20-30+ mins anyway, so an additional 8 mins should be okay for now. We could then gradually improve speed/performance over time.

Overall, I don't really have a strong preference. Whatever works best for you in terms of speed/pricing.

@dscho
Copy link
Member

dscho commented Dec 22, 2022

we could leave it as-is for now and create an issue in https://github.com/Azure/arm-deploy/ for them to add a "fire and forget" feature. WDYT?

Let's leave it as-is for now and if it becomes a problem, think about using Azure CLI directly (no need to go through the arm-deploy Action).

We could simply spin up the runner on demand instead, after all, a ~8 minute queue time is not that terrible for jobs that will run only once in a while

We could certainly start with that. Most builds/pipelines take 20-30+ mins anyway, so an additional 8 mins should be okay for now. We could then gradually improve speed/performance over time.

Overall, I don't really have a strong preference. Whatever works best for you in terms of speed/pricing.

Let's continue with the pre-spun-up strategy.

@dscho dscho merged commit a538b16 into git-for-windows:main Dec 22, 2022
@dscho
Copy link
Member

dscho commented Dec 22, 2022

Even if the build failed that used the self-hosted runner, the workflow run that created that self-hosted runner worked, so I merged it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants