Skip to content

Instantly share code, notes, and snippets.

@justinyoo
Last active March 25, 2020 04:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinyoo/0516447045d0ef3c606d7e84f0ecd872 to your computer and use it in GitHub Desktop.
Save justinyoo/0516447045d0ef3c606d7e84f0ecd872 to your computer and use it in GitHub Desktop.
Scheduling Posts with GitOps, Durable Functions and GitHub Actions
{
"owner": "aliencube",
"repository": "blog",
"issueId": 3,
"schedule": "2020-03-25T07:00:00+09:00"
}
{
"owner": "devkimchi",
"repository": "blog",
"issueId": 3,
"schedule": "2020-03-25T07:00:00+09:00"
}
[FunctionName("SetSchedule")]
public async Task<HttpResponseMessage> SetSchedule(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "orchestrators/{orchestratorName}")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
string orchestratorName,
ILogger log)
{
var input = await req.Content.ReadAsAsync<EventSchedulingRequest>();
var instanceId = await starter.StartNewAsync<EventSchedulingRequest>(orchestratorName, instanceId: null, input: input);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
[FunctionName("schedule-event")]
public async Task<object> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
var input = context.GetInput<EventSchedulingRequest>();
// Set the maximum duration. Max duration can't exceed 7 days.
var maxDuration = TimeSpan.Parse(Environment.GetEnvironmentVariable("Duration__Max"), CultureInfo.InvariantCulture);
if (maxDuration > threshold)
{
return "Now allowed";
}
// Get the scheduled time
var scheduled = input.Schedule.UtcDateTime;
// Get the function initiated time.
var initiated = context.CurrentUtcDateTime;
// Get the difference between now and schedule
var datediff = (TimeSpan)(scheduled - initiated);
// Complete if datediff is longer than the max duration
if (datediff >= maxDuration)
{
return "Too far away";
}
await context.CreateTimer(scheduled, CancellationToken.None);
var output = await context.CallActivityAsync<object>("CallRepositoryDispatchEvent", input);
return output;
}
[FunctionName("CallMergePrRepositoryDispatchEvent")]
public async Task<object> MergePr(
[ActivityTrigger] EventSchedulingRequest input,
ILogger log)
{
var authKey = Environment.GetEnvironmentVariable("GitHub__AuthKey");
var requestUri = $"{Environment.GetEnvironmentVariable("GitHub__BaseUri").TrimEnd('/')}/repos/{input.Owner}/{input.Repository}/{Environment.GetEnvironmentVariable("GitHub__Endpoints__Dispatches").TrimStart('/')}";
var accept = Environment.GetEnvironmentVariable("GitHub__Headers__Accept");
var userAgent = Environment.GetEnvironmentVariable("GitHub__Headers__UserAgent");
this._client.DefaultRequestHeaders.Clear();
this._client.DefaultRequestHeaders.Add("Authorization", authKey);
this._client.DefaultRequestHeaders.Add("Accept", accept);
this._client.DefaultRequestHeaders.Add("User-Agent", userAgent);
var payload = new RepositoryDispatchEventRequest<EventSchedulingRequest>("merge-pr", input);
using (var content = new ObjectContent<RepositoryDispatchEventRequest<EventSchedulingRequest>>(payload, this._formatter, "application/json"))
using (var response = await this._client.PostAsync(requestUri, content).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
}
return payload;
}
[FunctionName("CallPublishRepositoryDispatchEvent")]
public async Task<IActionResult> Publish(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "events/publish")] HttpRequest req,
ILogger log)
{
var input = JsonConvert.DeserializeObject<EventRequest>(await new StreamReader(req.Body).ReadToEndAsync());
var authKey = Environment.GetEnvironmentVariable("GitHub__AuthKey");
var requestUri = $"{Environment.GetEnvironmentVariable("GitHub__BaseUri").TrimEnd('/')}/repos/{input.Owner}/{input.Repository}/{Environment.GetEnvironmentVariable("GitHub__Endpoints__Dispatches").TrimStart('/')}";
var accept = Environment.GetEnvironmentVariable("GitHub__Headers__Accept");
var userAgent = Environment.GetEnvironmentVariable("GitHub__Headers__UserAgent");
this._client.DefaultRequestHeaders.Clear();
this._client.DefaultRequestHeaders.Add("Authorization", authKey);
this._client.DefaultRequestHeaders.Add("Accept", accept);
this._client.DefaultRequestHeaders.Add("User-Agent", userAgent);
var payload = new RepositoryDispatchEventRequest<EventSchedulingRequest>("publish", input);
using (var content = new ObjectContent<RepositoryDispatchEventRequest<EventSchedulingRequest>>(payload, this._formatter, "application/json"))
using (var response = await this._client.PostAsync(requestUri, content).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
}
return payload;
}
name: Merge PR
on: repository_dispatch
jobs:
merge_pr:
name: Merge PR
if: github.event.action == 'merge-pr'
runs-on: ubuntu-latest
steps:
- name: Merge PR
uses: justinyoo/github-pr-merge-action@v0.8.0
with:
authToken: ${{ secrets.GITHUB_TOKEN }}
owner: ${{ github.event.client_payload.owner }}
repository: ${{ github.event.client_payload.repository }}
issueId: '${{ github.event.client_payload.issueId }}'
mergeMethod: Squash
commitTitle: ''
commitDescription: ''
deleteBranch: 'true'
- name: Send dispatch event for publish
shell: bash
run: |
curl -X POST 'https://${{ secrets.AZURE_FUNCTIONS_NAME }}.azurewebsites.net/api/events/publish' -d '{ "owner": "${{ secrets.OWNER }}", "repository": "${{ secrets.REPOSITORY }}" }' -H "x-functions-key: ${{ secrets.AZURE_FUNCTIONS_KEY }}" -H "Content-Type: application/json"
build_and_publish:
name: Build and publish
if: github.event.action == 'publish'
runs-on: ubuntu-latest
steps:
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment