How can I falsify/fast-forward the runner's system clock?

I would like to increment the system clock on a GitHub-hosted runner, as part of our CI suite involves a test that should pass only if the system clock is a certain number of days after the product’s build date. i.e. We build the product, incremement the clock by X number of days, attempt to run the product and then the product should refuse to work and the test will pass.

This is all working except for the actual business of incrementing the system clock. How can I accomplish this? Ideally on Windows but in Linux as well.

I’ve tried setting the system clock by running: sudo date --set='+20 days', then checking it by running date however that doesn’t seem to actually increment the date. Does anyone have any suggestions?

1 Like

On Linux it seems to be required to intercept system calls with e.g. libfaketime, at least if you use Docker containers (date --set and hwclock are not permitted):

Something like this:

- name: Build and install libfaketime
  run: |
    git clone
    cd libfaketime
    make install

- name: Test with actual time
  run: date

- name: Test with fake time
    FAKETIME: +20 days
    LD_PRELOAD: /usr/local/lib/faketime/
  run: date

On Windows with PowerShell, you can use the following command:

Set-Date -Adjust (New-TimeSpan -Days 20)

However, this requires elevated rights. I’m not sure if PowerShell is run as administrator in GitHub hosted runners, or if you can elevate a process. I found scripts online which trigger a UAC prompt like so:

Start-Process powershell.exe "-Command `"Set-Date -Adjust (New-TimeSpan -Days 20)`"" -Verb RunAs

but no idea what it does in a headless environment, if it works at all.

Ubuntu has package faketime and libfaketime, so on the default runner VMs you can just install those instead of compiling.

Libfaketime works for linux, thanks. Any solutions for Windows?

My solution works just fine. I guess the runners run as admin or without UAC:

One potential thing to look out for: the system might have automatic clock adjustment enabled and sync it again to actual time at some point.

1 Like

Awesome! I shall give this a go! Although I notice github now thinks the job has taken 20 days… :confused:

Just set the time back, then the duration will be correct.

name: Fake time
on: push
    runs-on: windows-latest
      - name: Before time change
        run: (Get-Date).toString()
      - name: Change time
        run: |
          (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters).Type
          Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters -Name Type -Value NoSync
          (Set-Date -Adjust (New-TimeSpan -Days 20)).toString()
          #[Threading.Thread]::Sleep($(New-TimeSpan -Minutes 1))
          (New-TimeSpan -Minutes 1).TotalSeconds | Start-Sleep
          (Set-Date -Adjust (New-TimeSpan -Days -20)).toString()
      - name: After time change
        run: (Get-Date).toString()
    runs-on: ubuntu-latest
      - run: sudo apt-get install libfaketime
      - name: actual time
        run: date
      - name: faketime
          FAKETIME: +20 days
          LD_PRELOAD: /usr/lib/x86_64-linux-gnu/faketime/
        run: date

This works on Ubuntu, however for Windows, sometimes the clock gets reset very soon after, which means that the command that depends on the date being later, fails. I’m wondering if there’s an auto-update/sync service I can disable before falsifying the time, but i’m not sure how?

That should not happen with my above code, because it turns off clock synchronization in the system:

Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters -Name Type -Value NoSync

Unfortunately this still does happen. Even after running that command, the clock still magically shifts back to the correct date - part way through the next step (in my case a maven run).

2021-02-04T10:53:27.9564296Z [INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ release-checks ---
2021-02-04T10:53:27.9989951Z [INFO] Using 'UTF-8' encoding to copy filtered resources.
2020-12-03T10:53:27.8152788Z [INFO] Using 'UTF-8' encoding to copy filtered properties files.

Can I disable the Windows time service entirely via Powershell on GitHub actions?

OK, so i’ve resolved the issue, by being more thorough when halting the services

Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time -Name Start -Value 4
net stop w32time
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters -Name Type -Value NoSync
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\TimeProviders\NtpClient -Name Enabled -Value 0

After running a long-running operation, the system time no longer randomly reverts back to the actual time after fast-forwarding it

1 Like